Dziedziczenie

Dziedziczenie służy do modelowania relacji "is-a" lub podtypowania w programowaniu obiektowym.

Określanie relacji dziedziczenia

Relacje dziedziczenia określa się przy użyciu inherit słowa kluczowego w deklaracji klasy. Podstawowa forma składniowa jest pokazana w poniższym przykładzie.

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

Klasa może mieć co najwyżej jedną bezpośrednią klasę bazową. Jeśli nie określisz klasy bazowej przy użyciu słowa kluczowego inherit , klasa niejawnie dziedziczy z System.Objectklasy .

Dziedziczone elementy członkowskie

Jeśli klasa dziedziczy z innej klasy, metody i składowe klasy bazowej są dostępne dla użytkowników klasy pochodnej tak, jakby były bezpośrednimi członkami klasy pochodnej.

Wszystkie powiązania let i parametry konstruktora są prywatne dla klasy i dlatego nie można uzyskać dostępu z klas pochodnych.

Słowo kluczowe base jest dostępne w klasach pochodnych i odwołuje się do wystąpienia klasy bazowej. Jest on używany jak identyfikator własny.

Metody wirtualne i przesłonięcia

Metody wirtualne (i właściwości) działają nieco inaczej w języku F# w porównaniu z innymi językami platformy .NET. Aby zadeklarować nowy wirtualny element członkowski, należy użyć słowa kluczowego abstract . Można to zrobić niezależnie od tego, czy udostępniasz domyślną implementację dla tej metody. W związku z tym pełna definicja metody wirtualnej w klasie bazowej jest zgodna z tym wzorcem:

abstract member [method-name] : [type]

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

W klasie pochodnej zastąpić tę metodę wirtualną następującym wzorcem:

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

Jeśli pominięto domyślną implementację w klasie bazowej, klasa bazowa stanie się klasą abstrakcyjną.

Poniższy przykład kodu ilustruje deklarację nowej metody function1 wirtualnej w klasie bazowej i sposób zastąpienia jej w klasie pochodnej.

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

Konstruktory i dziedziczenie

Konstruktor klasy bazowej musi być wywoływany w klasie pochodnej. Argumenty konstruktora klasy bazowej są wyświetlane na liście argumentów w klauzuli inherit . Używane wartości muszą być określane z argumentów dostarczonych do konstruktora klasy pochodnej.

Poniższy kod przedstawia klasę bazową i klasę pochodną, gdzie klasa pochodna wywołuje konstruktora klasy bazowej w klauzuli dziedziczącej:

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

W przypadku wielu konstruktorów można użyć następującego kodu. Pierwszy wiersz konstruktorów klasy pochodnej to klauzula inherit , a pola są wyświetlane jako jawne pola zadeklarowane za pomocą słowa kluczowego val . Aby uzyskać więcej informacji, zobacz Jawne pola: val Słowo kluczowe.

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")

Alternatywy dla dziedziczenia

W przypadkach, gdy wymagana jest niewielka modyfikacja typu, rozważ użycie wyrażenia obiektu jako alternatywy dla dziedziczenia. W poniższym przykładzie pokazano użycie wyrażenia obiektu jako alternatywy dla utworzenia nowego typu pochodnego:

open System

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

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

Aby uzyskać więcej informacji na temat wyrażeń obiektów, zobacz Wyrażenia obiektów.

Podczas tworzenia hierarchii obiektów rozważ użycie dyskryminowanego związku zamiast dziedziczenia. Związki dyskryminowane mogą również modelować zróżnicowane zachowanie różnych obiektów, które mają wspólny typ ogólny. Pojedynczy związek dyskryminowany może często wyeliminować potrzebę wielu klas pochodnych, które są drobnymi odmianami siebie nawzajem. Aby uzyskać informacje o dyskryminowanych związkach zawodowych, zobacz Dyskryminowane związki zawodowe.

Zobacz też