Métodos (F#)

Un método es una función que está asociada a un tipo.En la programación orientada a objetos, los métodos se utilizan para exponer e implementar las funcionalidades y el comportamiento de los objetos y los tipos.

// Instance method definition.
[ attributes ]
member [inline] self-identifier.method-name parameter-list [ : return-type ]=
    method-body

// Static method definition.
[ attributes ]
static member [inline] method-name parameter-list [ : return-type ]=
    method-body

// Abstract method declaration or virtual dispatch slot.
[ attributes ]
abstract member self-identifier.method-name : type-signature

// Virtual method declaration and default implementation.
[ attributes ]
abstract member [inline] self-identifier.method-name : type-signature
[ attributes ]
default member [inline] self-identifier.method-name parameter-list[ : return-type ] =
    method-body

// Override of inherited virtual method.
[ attributes ]
override member [inline] self-identifier.method-name parameter-list [ : return-type ]=
    method-body

Comentarios

En la sintaxis anterior, se pueden observar las distintas formas de declaraciones y definiciones de métodos.En los cuerpos de método más largos, aparece un salto de línea detrás del signo igual (=) y se aplica sangría al cuerpo del método completo.

Se pueden aplicar atributos a cualquier declaración de método.Preceden a la sintaxis para una definición de método y se suelen enumerar en una línea independiente.Para obtener más información, vea Atributos (F#).

Los métodos se pueden marcar con inline.Para obtener información sobre inline, vea Funciones inline (F#).

Los métodos que no son inline se pueden utilizar de forma recursiva dentro del tipo; no hay ninguna necesidad de utilizar la palabra clave rec explícitamente.

Métodos de instancia

Los métodos de instancia se declaran con la palabra clave member y self-identifier, seguidos de un punto (.) y del nombre y los parámetros del método.Como sucede con los enlaces let, parameter-list puede ser un modelo.Normalmente, los parámetros del método se incluyen entre paréntesis en forma de tupla, que es la manera en que aparecen los métodos en F# cuando se han creado en otros lenguajes .NET Framework.Sin embargo, también es común la forma currificada (parámetros separados por espacios) y se admiten asimismo otros modelos.

En el ejemplo siguiente se muestran la definición y el uso de un método de instancia no abstracto.

type SomeType(factor0: int) =
   let factor = factor0
   member this.SomeMethod(a, b, c) =
      (a + b + c) * factor

   member this.SomeOtherMethod(a, b, c) =
      this.SomeMethod(a, b, c) * factor

En los métodos de instancia no se utiliza el autoidentificador para tener acceso a los campos definidos mediante enlaces.El autoidentificador se utiliza para tener acceso a otros miembros y propiedades.

Métodos estáticos

La palabra clave static se utiliza para especificar que se puede llamar a un método sin una instancia y que no está asociado a una instancia de objeto.De lo contrario, los métodos son de instancia.

En el ejemplo de la sección siguiente se muestran campos declarados con la palabra clave let, miembros de propiedad declarados con la palabra clave member y un método estático declarado con la palabra clave static.

En el ejemplo siguiente se muestran la definición y el uso de los métodos estáticos.Se da por hecho que estas definiciones de método están en la clase SomeType de la sección anterior.

static member SomeStaticMethod(a, b, c) =
   (a + b + c)

static member SomeOtherStaticMethod(a, b, c) =
   SomeType.SomeStaticMethod(a, b, c) * 100

Métodos abstractos y virtuales

La palabra clave abstract indica que un método tiene una entrada de distribución virtual y que es posible que no tenga una definición en la clase.Una entrada de distribución virtual es una entrada de una tabla de funciones mantenida internamente que se usa en tiempo de ejecución para buscar llamadas de función virtuales en un tipo orientado a objetos.El mecanismo de distribución virtual es el que implementa el polimorfismo, una característica importante de la programación orientada a objetos.Una clase que tiene al menos un método abstracto sin una definición es una clase abstracta, lo que significa que no se puede crear ninguna instancia de esa clase.Para obtener más información sobre las clases abstractas, vea Clases abstractas (F#).

Las declaraciones de métodos abstractos no incluyen un cuerpo de método.En su lugar, el nombre del método va seguido de dos puntos (:) y una signatura de tipo para el método.La signatura de tipo de un método es la misma que muestra IntelliSense cuando se sitúa el puntero del mouse sobre el nombre de un método en el Editor de código de Visual Studio, exceptuando los nombres de parámetro.También el intérprete, fsi.exe, muestra las signaturas de tipo cuando se trabaja interactivamente.La signatura de tipo de un método se forma enumerando los tipos de los parámetros, seguidos por el tipo de valor devuelto, con símbolos separadores adecuados.Los parámetros currificados se separan por -> y los parámetros de tupla se separan por *.El valor devuelto siempre se separa de los argumentos mediante el símbolo ->.Se pueden utilizar paréntesis para agrupar parámetros complejos, por ejemplo, cuando un tipo de función es un parámetro, o para indicar cuándo una tupla se trata como un solo parámetro en lugar de como dos parámetros.

También se pueden proporcionar definiciones predeterminadas a los métodos abstractos; para ello, se agrega la definición a la clase y se utiliza la palabra clave default, como se muestra en el bloque de sintaxis de este tema.Un método abstracto que tiene una definición en la misma clase es equivalente a un método virtual de otros lenguajes .NET Framework.Con independencia de si una definición existe o no, la palabra clave abstract crea una nueva entrada de distribución en la tabla de funciones virtuales para la clase.

Sin tener en cuenta si una clase base implementa sus métodos abstractos, las clases derivadas pueden proporcionar implementaciones de métodos abstractos.Para implementar un método abstracto en una clase derivada, se define un método que tiene el mismo nombre y la misma signatura en la clase derivada, con la salvedad de que se usa la palabra clave default u override y se proporciona el cuerpo del método.Las palabras clave override y default significan exactamente lo mismo.override se utiliza si el nuevo método reemplaza una implementación de la clase base; default se utiliza al crear una implementación en la misma clase como declaración abstracta original.La palabra clave abstract no se utiliza en el método que implementa el método que se declaró como abstracto en la clase base.

En el ejemplo siguiente, se muestra un método Rotate abstracto que tiene una implementación predeterminada, el equivalente de un método virtual de .NET Framework.

type Ellipse(a0 : float, b0 : float, theta0 : float) =
    let mutable axis1 = a0
    let mutable axis2 = b0
    let mutable rotAngle = theta0
    abstract member Rotate: float -> unit
    default this.Rotate(delta : float) = rotAngle <- rotAngle + delta

En el ejemplo siguiente se muestra una clase derivada que reemplaza un método de clase base.En este caso, el reemplazo cambia el comportamiento para que el método no haga nada.

type Circle(radius : float) =
    inherit Ellipse(radius, radius, 0.0)
     // Circles are invariant to rotation, so do nothing.
    override this.Rotate(_) = ()

Métodos sobrecargados

Los métodos sobrecargados son métodos que tienen nombres idénticos en un tipo determinado pero que tienen argumentos diferentes.En F#, se suelen utilizar argumentos opcionales en lugar de métodos sobrecargados.Sin embargo, el lenguaje admite los métodos sobrecargados, siempre que los argumentos estén en forma de tupla, y no en forma currificada.

Ejemplo: propiedades y métodos

El ejemplo siguiente contiene un tipo que tiene ejemplos de campos, funciones privadas, propiedades y un método estático.

type RectangleXY(x1 : float, y1: float, x2: float, y2: float) =
    // Field definitions.
    let height = y2 - y1
    let width = x2 - x1
    let area = height * width
    // Private functions.
    static let maxFloat (x: float) (y: float) =
      if x >= y then x else y
    static let minFloat (x: float) (y: float) =
      if x <= y then x else y
    // Properties.
    // Here, "this" is used as the self identifier,
    // but it can be any identifier.
    member this.X1 = x1
    member this.Y1 = y1
    member this.X2 = x2
    member this.Y2 = y2
    // A static method.
    static member intersection(rect1 : RectangleXY, rect2 : RectangleXY) =
       let x1 = maxFloat rect1.X1 rect2.X1
       let y1 = maxFloat rect1.Y1 rect2.Y1
       let x2 = minFloat rect1.X2 rect2.X2
       let y2 = minFloat rect1.Y2 rect2.Y2
       let result : RectangleXY option =
         if ( x2 > x1 && y2 > y1) then
           Some (RectangleXY(x1, y1, x2, y2))
         else
           None
       result

// Test code.
let testIntersection =
    let r1 = RectangleXY(10.0, 10.0, 20.0, 20.0)
    let r2 = RectangleXY(15.0, 15.0, 25.0, 25.0)
    let r3 : RectangleXY option = RectangleXY.intersection(r1, r2)
    match r3 with
    | Some(r3) -> printfn "Intersection rectangle: %f %f %f %f" r3.X1 r3.Y1 r3.X2 r3.Y2
    | None -> printfn "No intersection found."

testIntersection

Vea también

Otros recursos

Miembros (F#)