Herencia
La herencia se usa para modelar la relación "is-a", o subtipado, en la programación orientada a objetos.
Especificar relaciones de herencia
Las relaciones de herencia se especifican mediante la palabra inherit clave en una declaración de clase. La forma sintáctica básica se muestra en el ejemplo siguiente.
type MyDerived(...) =
inherit MyBase(...)
Una clase puede tener como máximo una clase base directa. Si no especifica una clase base mediante la palabra inherit clave , la clase hereda implícitamente de System.Object .
Miembros heredados
Si una clase hereda de otra clase, los métodos y miembros de la clase base están disponibles para los usuarios de la clase derivada como si fueran miembros directos de la clase derivada.
Los enlaces let y los parámetros de constructor son privados para una clase y, por lo tanto, no se puede acceder a ellos desde clases derivadas.
La palabra base clave está disponible en clases derivadas y hace referencia a la instancia de clase base. Se usa como el identificador propio.
Métodos virtuales e invalidaciones
Los métodos virtuales (y las propiedades) funcionan de forma ligeramente diferente en F# en comparación con otros lenguajes .NET. Para declarar un nuevo miembro virtual, use la palabra abstract clave . Esto se hace independientemente de si se proporciona una implementación predeterminada para ese método. Por lo tanto, una definición completa de un método virtual en una clase base sigue este patrón:
abstract member [method-name] : [type]
default [self-identifier].[method-name] [argument-list] = [method-body]
Y en una clase derivada, una invalidación de este método virtual sigue este patrón:
override [self-identifier].[method-name] [argument-list] = [method-body]
Si omite la implementación predeterminada en la clase base, la clase base se convierte en una clase abstracta.
En el ejemplo de código siguiente se muestra la declaración de un nuevo método virtual en una clase base y cómo function1 invalidarlo en una clase derivada.
type MyClassBase1() =
let mutable z = 0
abstract member function1 : int -> int
default u.function1(a : int) = z <- z + a; z
type MyClassDerived1() =
inherit MyClassBase1()
override u.function1(a: int) = a + 1
Constructores y herencia
Se debe llamar al constructor de la clase base en la clase derivada. Los argumentos del constructor de clase base aparecen en la lista de argumentos de la inherit cláusula . Los valores que se usan deben determinarse a partir de los argumentos proporcionados al constructor de clase derivada.
El código siguiente muestra una clase base y una clase derivada, donde la clase derivada llama al constructor de clase base en la cláusula inherit:
type MyClassBase2(x: int) =
let mutable z = x * x
do for i in 1..z do printf "%d " i
type MyClassDerived2(y: int) =
inherit MyClassBase2(y * 2)
do for i in 1..y do printf "%d " i
En el caso de varios constructores, se puede usar el código siguiente. La primera línea de los constructores de clase derivada es la cláusula y los campos aparecen como campos explícitos que inherit se declaran con la palabra val clave . Para obtener más información, vea Campos explícitos: la val palabra clave.
type BaseClass =
val string1 : string
new (str) = { string1 = str }
new () = { string1 = "" }
type DerivedClass =
inherit BaseClass
val string2 : string
new (str1, str2) = { inherit BaseClass(str1); string2 = str2 }
new (str2) = { inherit BaseClass(); string2 = str2 }
let obj1 = DerivedClass("A", "B")
let obj2 = DerivedClass("A")
Alternativas a la herencia
En los casos en los que se requiere una modificación menor de un tipo, considere la posibilidad de usar una expresión de objeto como alternativa a la herencia. En el ejemplo siguiente se muestra el uso de una expresión de objeto como alternativa a la creación de un nuevo tipo derivado:
open System
let object1 = { new Object() with
override this.ToString() = "This overrides object.ToString()"
}
printfn "%s" (object1.ToString())
Para obtener más información sobre las expresiones de objeto, vea Expresiones de objeto.
Al crear jerarquías de objetos, considere la posibilidad de usar una unión discriminada en lugar de la herencia. Las uniones discriminadas también pueden modelar un comportamiento variado de distintos objetos que comparten un tipo general común. Una única unión discriminada a menudo puede eliminar la necesidad de un número de clases derivadas que son pequeñas variaciones entre sí. Para obtener información sobre las uniones discriminadas, vea Uniones discriminadas.