Ler em inglês

Compartilhar via


Herança

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

Como especificar relações de herança

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

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

Uma classe derivada pode ter apenas uma classe base direta. Se você não especificar uma classe base usando a palavra-chave inherit, a classe herda 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.

Qualquer associação e parâmetros de 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 autoidentificador.

Métodos virtuais e substituições

Os métodos virtuais (e as propriedades) funcionam de forma um pouco diferente no F# em comparação com outras linguagens .NET. Para declarar um novo membro virtual, use a palavra-chave abstract. 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 virtual function1 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 cláusula inherit e os campos aparecem como campos explícitos declarados com a palavra-chave val. Para mais informações, consulte Campos explícitos: a palavra-chave 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 à 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 saber mais sobre expressões de objeto, consulte o artigo sobre Expressões de objeto.

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

Confira também