Compartir vía


Herencia

La herencia se usa para modelar la relación "is-a" o subtyping, en la programación orientada a objetos.

Especificar relaciones de herencia

Las relaciones de herencia se especifican mediante la inherit palabra clave en una declaración de clase. El formulario sintáctico básico 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 inherit palabra 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 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 virtuales (y propiedades) funcionan de forma algo diferente en F# en comparación con otros lenguajes .NET. Para declarar un nuevo miembro virtual, use la abstract palabra 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 function1 virtual en una clase base y cómo 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 en la cláusula inherit. 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 inherit cláusula y los campos aparecen como campos explícitos declarados con la val palabra 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 secundaria 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 diferentes objetos que comparten un tipo general común. Una sola unión discriminada a menudo puede eliminar la necesidad de una serie de clases derivadas que son variaciones menores entre sí. Para obtener información sobre las uniones discriminadas, vea Uniones discriminadas.

Consulte también