Interfaces (F#)
Las interfaces especifican conjuntos de miembros relacionados que otras clases implementan.
// Interface declaration:
[ attributes ]
type interface-name =
[ interface ]
[ inherit base-interface-name ...]
abstract member1 : [ argument-types1 -> ] return-type1
abstract member2 : [ argument-types2 -> ] return-type2
...
[ end ]
// Implementing, inside a class type definition:
interface interface-name with
member self-identifier.member1 argument-list = method-body1
member self-identifier.member2 argument-list = method-body2
// Implementing, by using an object expression:
[ attributes ]
let class-name (argument-list) =
{ new interface-name with
member self-identifier.member1 argument-list = method-body1
member self-identifier.member2 argument-list = method-body2
[ base-interface-definitions ]
}
member-list
Comentarios
Las declaraciones de interfaz se parecen las declaraciones de clase, pero no implementan miembros.En cambio, todos los miembros son abstractos, tal y como se indica mediante la palabra clave abstract.Para los métodos abstractos no se proporciona el cuerpo del método.No obstante, se puede proporcionar una implementación predeterminada incluyendo, además, una definición independiente del miembro como método junto con la palabra clave default.Esto equivale a crear un método virtual en una clase base en otros lenguajes .NET.Un método virtual de este tipo se puede reemplazar en las clases que implementan la interfaz.
Hay dos maneras de implementar interfaces: mediante expresiones de objeto y mediante tipos de clase.En ambos casos, el tipo de clase o la expresión de objeto proporciona los cuerpos para los métodos abstractos de la interfaz.Las implementaciones son específicas de cada tipo que implementa la interfaz.Por consiguiente, los métodos de interfaz para tipos diferentes podrían ser distintos.
Las palabras clave interface y end, que marcan el inicio y el final de la definición, son opcionales cuando se utiliza la sintaxis ligera.Si no utiliza estas palabras clave, el compilador intenta deducir si el tipo es una clase o una interfaz analizando las construcciones utilizadas.Si se define un miembro o se utiliza otra sintaxis de clase, se interpreta que el tipo es una clase.
En el estilo de codificación de .NET, todas las interfaces empiezan por una letra I mayúscula.
Implementar interfaces mediante tipos de clase
Se puede implementar una o más interfaces en un tipo de clase mediante la palabra clave interface, el nombre de la interfaz, la palabra clave with y, a continuación, las definiciones de los miembros de la interfaz, como se muestra en el código siguiente.
type IPrintable =
abstract member Print : unit -> unit
type SomeClass1(x: int, y: float) =
interface IPrintable with
member this.Print() = printfn "%d %f" x y
Las implementaciones de interfaz se heredan, por lo que las clases derivadas no necesitan volver a implementarlas.
Llamar a métodos de interfaz
Únicamente se puede llamar a los métodos de interfaz a través de la interfaz, y no a través de ningún objeto del tipo que implementa la interfaz.Así pues, es posible que sea necesario realizar una conversión hacia arriba en el tipo de interfaz utilizando el operador :> o el operador upcast para llamar a estos métodos.
Para llamar al método de interfaz cuando hay un objeto de tipo SomeClass, hay que realizar la conversión hacia arriba del objeto en el tipo de interfaz, como se muestra en el código siguiente.
let x1 = new SomeClass1(1, 2.0)
(x1 :> IPrintable).Print()
Una alternativa consiste en declarar un método para el objeto que realiza la conversión hacia arriba y llamar al método de interfaz, como en el ejemplo siguiente.
type SomeClass2(x: int, y: float) =
member this.Print() = (this :> IPrintable).Print()
interface IPrintable with
member this.Print() = printfn "%d %f" x y
let x2 = new SomeClass2(1, 2.0)
x2.Print()
Implementar interfaces mediante expresiones de objeto
Las expresiones de objeto proporcionan una manera breve de implementar una interfaz.Resultan útiles cuando no se tiene que crear un tipo con nombre y únicamente se precisa un objeto que admita los métodos de interfaz, sin ningún método adicional.En el código siguiente se muestra una expresión de objeto.
let makePrintable(x: int, y: float) =
{ new IPrintable with
member this.Print() = printfn "%d %f" x y }
let x3 = makePrintable(1, 2.0)
x3.Print()
Herencia de interfaz
Las interfaces pueden heredar de una o varias interfaces base.
type Interface1 =
abstract member Method1 : int -> int
type Interface2 =
abstract member Method2 : int -> int
type Interface3 =
inherit Interface1
inherit Interface2
abstract member Method3 : int -> int
type MyClass() =
interface Interface3 with
member this.Method1(n) = 2 * n
member this.Method2(n) = n + 100
member this.Method3(n) = n / 10