Herencia

La herencia se usa para modelar la relación de identidad o los subtipos en la programación orientada a objetos.

Especificación de relaciones de herencia

Las relaciones de herencia se especifican mediante la palabra clave inherit en una declaración de clase. En el ejemplo siguiente se muestra el formulario sintáctico básico.

type MyDerived(...) =
    inherit MyBase(...)

Una clase puede tener como mucho una clase base directa. Si no especifica una clase base mediante la palabra clave inherit, 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 tener acceso a ellos desde clases derivadas.

La palabra clave base 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 (y propiedades) virtuales funcionan de forma ligeramente diferente en F# en comparación con otros lenguajes .NET. Para declarar un nuevo miembro virtual, use la palabra clave abstract. 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]

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, esta se convierte en una clase abstracta.

En el ejemplo de código siguiente se muestra la declaración de un nuevo método virtual function1 en una clase base y cómo se invalida 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 en la cláusula inherit. Los valores que se usan deben determinarse a partir de los argumentos proporcionados al constructor de clase derivada.

En el código siguiente se 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 inherit y los campos aparecen como campos explícitos declarados con la palabra clave val. Para obtener más información, consulte Campos explícitos: la palabra clave val.

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 leve modificación 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 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, consulte 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 sola unión discriminada a menudo puede eliminar la necesidad de varias clases derivadas que son leves variaciones entre sí. Para obtener información sobre las uniones discriminadas, consulte Uniones discriminadas.

Consulte también