Partilhar 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

Você especifica relações de herança usando a inherit palavra-chave em uma declaração de classe. A forma sintática básica é mostrada 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 herda de outra classe, os métodos e membros da classe base estarão disponíveis para os usuários da classe derivada como se fossem membros diretos da classe derivada.

Todas as ligações de permissão e parâmetros do construtor são privados para uma classe e, portanto, não podem ser acessados a partir de classes derivadas.

A palavra-chave base está disponível em classes derivadas e refere-se à instância da classe base. É usado como o autoidentificador.

Métodos virtuais e substituições

Os 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 palavra-chave abstract . Você faz isso independentemente de fornecer uma implementação padrão para esse método. Assim, 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 para a classe base deve ser chamado na classe derivada. Os argumentos para o construtor de classe base aparecem na lista de argumentos na inherit cláusula. Os valores usados devem ser determinados a partir dos argumentos fornecidos ao construtor de classe derivada.

O código a seguir mostra uma classe base e uma classe derivada, onde a classe derivada chama o construtor de classe base na 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

No caso de vários construtores, o código a seguir pode ser usado. A primeira linha dos construtores de classe derivados é a inherit cláusula e os campos aparecem como campos explícitos que são declarados com a palavra-chave val . 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 alternativa à herança. O exemplo a seguir ilustra o uso de uma expressão de objeto como uma alternativa para criar 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 objetos, considere usar uma união discriminada em vez de herança. Uniões discriminadas também podem modelar comportamentos variados de diferentes objetos que compartilham um tipo geral comum. Uma única união discriminada pode muitas vezes 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 Sindicatos discriminados.

Consulte também