Compartilhar via


Herança

A herança é usada para modelar a relação "is-a", ou subtipagem, na programação orientada a objetos.

Especificando relações de herança

Especifique relações de herança usando a inherit palavra-chave em uma declaração de classe. O formulário sintático básico é mostrado no exemplo a seguir.

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

Uma classe pode ter no máximo uma classe base direta. Se você não especificar uma classe base usando a inherit palavra-chave, a classe herdará implicitamente de System.Object.

Membros herdados

Se uma classe herdar de outra classe, os métodos e os membros da classe base estarão disponíveis para os usuários da classe derivada como se fossem membros diretos da classe derivada.

As associações let e os parâmetros do construtor são privados para uma classe e, portanto, não podem ser acessados de classes derivadas.

A palavra-chave base está disponível em classes derivadas e refere-se à instância de classe base. Ele é usado como o auto-identificador.

Métodos virtuais e substituições

Métodos virtuais (e propriedades) funcionam de forma um pouco diferente em F# em comparação com outras linguagens .NET. Para declarar um novo membro virtual, use a abstract palavra-chave. Você faz isso independentemente de fornecer uma implementação padrão para esse método. Portanto, uma definição completa de um método virtual em uma classe base segue este padrão:

abstract member [method-name] : [type]

default [self-identifier].[method-name] [argument-list] = [method-body]

E em uma classe derivada, uma substituição desse método virtual segue este padrão:

override [self-identifier].[method-name] [argument-list] = [method-body]

Se você omitir a implementação padrão na classe base, a classe base se tornará uma classe abstrata.

O exemplo de código a seguir ilustra a declaração de um novo método function1 virtual em uma classe base e como substituí-lo em uma classe 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

Construtores e herança

O construtor da classe base deve ser chamado na classe derivada. Os argumentos para o construtor de classe base aparecem na lista de argumentos na cláusula inherit. Os valores usados devem ser determinados dos argumentos fornecidos ao construtor de classe derivada.

O código a seguir mostra uma classe base e uma classe derivada, em que a classe derivada chama o construtor de classe base na cláusula herdada:

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

No caso de vários construtores, o código a seguir pode ser usado. A primeira linha dos construtores de classe derivada é a inherit cláusula e os campos aparecem como campos explícitos que são declarados com a val palavra-chave. Para obter mais informações, consulte Campos Explícitos: a val palavra-chave.

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 à herança

Nos casos em que uma pequena modificação de um tipo é necessária, considere usar uma expressão de objeto como uma alternativa à herança. O exemplo a seguir ilustra o uso de uma expressão de objeto como uma alternativa à criação de um novo tipo derivado:

open System

let object1 =
    { new Object() with
        override this.ToString() = "This overrides object.ToString()" }

printfn "%s" (object1.ToString())

Para obter mais informações sobre expressões de objeto, consulte Expressões de Objeto.

Ao criar hierarquias de objeto, considere usar uma união discriminada em vez de herança. Uniões discriminadas também podem modelar comportamentos variados de objetos diferentes que compartilham um tipo geral comum. Uma única união discriminada geralmente pode eliminar a necessidade de várias classes derivadas que são pequenas variações umas das outras. Para obter informações sobre sindicatos discriminados, consulte Uniões Discriminadas.

Consulte também