Dědičnost
Dědičnost se používá k modelování relace "is-a" nebo podtypu v objektově orientovaném programování.
Určení vztahů dědičnosti
Relace dědičnosti určíte pomocí klíčového inherit
slova v deklaraci třídy. Základní syntaktický formulář je znázorněn v následujícím příkladu.
type MyDerived(...) =
inherit MyBase(...)
Třída může mít maximálně jednu přímou základní třídu. Pokud nezadáte základní třídu pomocí klíčového inherit
slova, třída implicitně dědí z System.Object
.
Zdědění členové
Pokud třída dědí z jiné třídy, jsou metody a členy základní třídy k dispozici uživatelům odvozené třídy, jako by byly přímí členy odvozené třídy.
Všechny vazby let a parametry konstruktoru jsou privátní pro třídu, a proto nelze získat přístup z odvozených tříd.
Klíčové slovo base
je k dispozici v odvozených třídách a odkazuje na instanci základní třídy. Používá se jako identifikátor sebe sama.
Virtuální metody a přepsání
Virtuální metody (a vlastnosti) fungují v jazyce F# poněkud jinak než v jiných jazycích .NET. Chcete-li deklarovat nového virtuálního člena abstract
, použijte klíčové slovo. Uděláte to bez ohledu na to, jestli pro tuto metodu zadáte výchozí implementaci. Kompletní definice virtuální metody v základní třídě se tedy řídí tímto vzorem:
abstract member [method-name] : [type]
default [self-identifier].[method-name] [argument-list] = [method-body]
A v odvozené třídě přepsání této virtuální metody se řídí tímto vzorem:
override [self-identifier].[method-name] [argument-list] = [method-body]
Pokud vynecháte výchozí implementaci v základní třídě, základní třída se stane abstraktní třídou.
Následující příklad kódu znázorňuje deklaraci nové virtuální metody function1
v základní třídě a jak ji přepsat v odvozené třídě.
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 a dědičnost
Konstruktor základní třídy musí být volána v odvozené třídě. Argumenty konstruktoru základní třídy se zobrazí v seznamu argumentů v klauzuli inherit
. Použité hodnoty musí být určeny z argumentů zadaných do konstruktoru odvozené třídy.
Následující kód ukazuje základní třídu a odvozenou třídu, kde odvozená třída volá konstruktor základní třídy v klauzuli 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
V případě více konstruktorů lze použít následující kód. První řádek konstruktorů odvozené třídy je inherit
klauzule a pole se zobrazí jako explicitní pole deklarovaná pomocí klíčového val
slova. Další informace naleznete v tématu Explicitní pole: Klíčové val
slovo.
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")
Alternativy k dědičnosti
V případech, kdy je vyžadována menší úprava typu, zvažte použití výrazu objektu jako alternativu k dědičnosti. Následující příklad znázorňuje použití výrazu objektu jako alternativu k vytvoření nového odvozeného typu:
open System
let object1 =
{ new Object() with
override this.ToString() = "This overrides object.ToString()" }
printfn "%s" (object1.ToString())
Další informace o výrazech objektů naleznete v tématu Výrazy objektů.
Při vytváření hierarchií objektů zvažte použití diskriminované sjednocení místo dědičnosti. Diskriminované sjednocení mohou také modelovat různé chování různých objektů, které sdílejí společný celkový typ. Jedna diskriminovaná sjednocení může často eliminovat potřebu řady odvozených tříd, které jsou drobné variace mezi sebou. Informace o diskriminovaných svazech naleznete v tématu Diskriminované sjednocení.