Overname
Overname wordt gebruikt om de 'is-a'-relatie, of subtyping, te modelleren in objectgeoriënteerde programmering.
Overnamerelaties opgeven
U geeft overnamerelaties op met behulp van het inherit
trefwoord in een klassedeclaratie. Het syntacticale basisformulier wordt weergegeven in het volgende voorbeeld.
type MyDerived(...) =
inherit MyBase(...)
Een klasse kan maximaal één directe basisklasse hebben. Als u geen basisklasse opgeeft met behulp van het inherit
trefwoord, neemt de klasse impliciet over van System.Object
.
Overgenomen leden
Als een klasse overdrat van een andere klasse, zijn de methoden en leden van de basisklasse beschikbaar voor gebruikers van de afgeleide klasse alsof ze directe leden van de afgeleide klasse zijn.
Bindingen en constructorparameters zijn privé voor een klasse en kunnen daarom niet worden geopend vanuit afgeleide klassen.
Het trefwoord base
is beschikbaar in afgeleide klassen en verwijst naar het exemplaar van de basisklasse. Het wordt gebruikt als de self-id.
Virtuele methoden en onderdrukkingen
Virtuele methoden (en eigenschappen) werken enigszins anders in F# in vergelijking met andere .NET-talen. Als u een nieuw virtueel lid wilt declareren, gebruikt u het abstract
trefwoord. U doet dit ongeacht of u een standaard implementatie voor die methode opgeeft. Een volledige definitie van een virtuele methode in een basisklasse volgt dus dit patroon:
abstract member [method-name] : [type]
default [self-identifier].[method-name] [argument-list] = [method-body]
En in een afgeleide klasse volgt een onderdrukking van deze virtuele methode dit patroon:
override [self-identifier].[method-name] [argument-list] = [method-body]
Als u de standaard implementatie in de basisklasse weglaat, wordt de basisklasse een abstracte klasse.
In het volgende codevoorbeeld ziet u de declaratie van een nieuwe virtuele methode function1
in een basisklasse en hoe u deze kunt overschrijven in een afgeleide klasse.
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
Constructors en overname
De constructor voor de basisklasse moet worden aangeroepen in de afgeleide klasse. De argumenten voor de basisklasseconstructor worden weergegeven in de argumentenlijst in de inherit
component. De waarden die worden gebruikt, moeten worden bepaald op basis van de argumenten die zijn opgegeven aan de afgeleide klasseconstructor.
De volgende code toont een basisklasse en een afgeleide klasse, waarbij de afgeleide klasse de basisklasseconstructor aanroept in de overnamecomponent:
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
In het geval van meerdere constructors kan de volgende code worden gebruikt. De eerste regel van de afgeleide klasseconstructors is de inherit
component en de velden worden weergegeven als expliciete velden die met het val
trefwoord worden gedeclareerd. Zie Expliciete velden: Het val
trefwoord voor meer informatie.
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")
Alternatieven voor overname
In gevallen waarin een kleine wijziging van een type vereist is, kunt u overwegen een objectexpressie te gebruiken als alternatief voor overname. In het volgende voorbeeld ziet u het gebruik van een objectexpressie als alternatief voor het maken van een nieuw afgeleid type:
open System
let object1 =
{ new Object() with
override this.ToString() = "This overrides object.ToString()" }
printfn "%s" (object1.ToString())
Zie Objectexpressies voor meer informatie over objectexpressies.
Wanneer u objecthiërarchieën maakt, kunt u overwegen een gediscrimineerde samenvoeging te gebruiken in plaats van overname. Gediscrimineerde vakbonden kunnen ook gevarieerd gedrag modelleren van verschillende objecten die een gemeenschappelijk algemeen type delen. Een enkele gediscrimineerde samenvoeging kan vaak voorkomen dat een aantal afgeleide klassen kleine variaties van elkaar zijn. Zie Gediscrimineerde vakbonden voor informatie over gediscrimineerde vakbonden.