Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Abstrakte Klassen sind Klassen , die einige oder alle Elemente nicht implementiert lassen, sodass Implementierungen von abgeleiteten Klassen bereitgestellt werden können.
Syntax
// Abstract class syntax.
[<AbstractClass>]
type [ accessibility-modifier ] abstract-class-name =
[ inherit base-class-or-interface-name ]
[ abstract-member-declarations-and-member-definitions ]
// Abstract member syntax.
abstract member member-name : type-signature
Bemerkungen
Bei der objektorientierten Programmierung wird eine abstrakte Klasse als Basisklasse einer Hierarchie verwendet und stellt allgemeine Funktionen einer vielzahl von Objekttypen dar. Wie der Name "abstract" impliziert, entsprechen abstrakte Klassen häufig nicht direkt konkreten Entitäten in der Problemdomäne. Sie stellen jedoch dar, was viele verschiedene konkrete Entitäten gemeinsam haben.
Abstrakte Klassen müssen über das AbstractClass Attribut verfügen. Sie können implementierte und nicht implementierte Mitglieder haben. Die Verwendung des Begriffs "Abstract " bei Anwendung auf eine Klasse ist identisch mit anderen .NET-Sprachen; Die Verwendung des Begriffs "Abstract " bei Anwendung auf Methoden (und Eigenschaften) unterscheidet sich jedoch etwas von der Verwendung in anderen .NET-Sprachen in F#. Wenn in F# eine Methode mit dem abstract Schlüsselwort gekennzeichnet ist, gibt dies an, dass ein Element einen Eintrag hat, der als virtueller Verteilerplatz bezeichnet wird, in der internen Tabelle der virtuellen Funktionen für diesen Typ. Mit anderen Worten, die Methode ist virtuell, obwohl das virtual Schlüsselwort nicht in F# verwendet wird. Das Schlüsselwort abstract wird für virtuelle Methoden verwendet, unabhängig davon, ob die Methode implementiert ist. Die Deklaration eines virtuellen Verteilerplatzes unterscheidet sich von der Definition einer Methode für diesen Verteilerplatz. Daher ist die F#-Entsprechung einer virtuellen Methodendeklaration und -definition in einer anderen .NET-Sprache eine Kombination aus einer abstrakten Methodendeklaration und einer separaten Definition, entweder mit dem default Schlüsselwort oder dem override Schlüsselwort. Weitere Informationen und Beispiele finden Sie unter "Methoden".
Eine Klasse wird nur als abstrakt betrachtet, wenn es abstrakte Methoden gibt, die deklariert, aber nicht definiert sind. Daher sind Klassen mit abstrakten Methoden nicht unbedingt abstrakte Klassen. Wenn eine Klasse nicht über nicht definierte abstrakte Methoden verfügt, verwenden Sie nicht das AbstractClass-Attribut .
In der vorherigen Syntax kann publicder Modifizierer für Barrierefreiheitsmodifizierer oder privateinternal. Weitere Informationen finden Sie unter Access Control.
Wie bei anderen Typen können abstrakte Klassen eine Basisklasse und eine oder mehrere Basisschnittstellen aufweisen. Jede Basisklasse oder Schnittstelle wird zusammen mit dem inherit Schlüsselwort in einer separaten Zeile angezeigt.
Die Typdefinition einer abstrakten Klasse kann vollständig definierte Member enthalten, aber sie kann auch abstrakte Member enthalten. Die Syntax für abstrakte Member wird in der vorherigen Syntax separat dargestellt. In dieser Syntax ist die Typsignatur eines Elements eine Liste, die die Parametertypen in der Reihenfolge und die Rückgabetypen enthält, getrennt durch -> Token und/oder * Token entsprechend für curriede und tupled-Parameter. Die Syntax für abstrakte Membertypsignaturen ist identisch mit denen, die in Signaturdateien verwendet werden und die von IntelliSense im Visual Studio Code-Editor angezeigt werden.
Der folgende Code veranschaulicht eine abstrakte Klasse Shape mit zwei nicht abstrakten abgeleiteten Klassen, Square und Circle. Das Beispiel zeigt, wie abstrakte Klassen, Methoden und Eigenschaften verwendet werden. Im Beispiel stellt die abstrakte Klasse Shape die allgemeinen Elemente der betonierten Entitäten Kreis und Quadrat dar. Die allgemeinen Merkmale aller Formen (in einem zweidimensionalen Koordinatensystem) werden in der Shape-Klasse abstrahiert: die Position im Raster, ein Drehwinkel und die Flächen- und Umkreiseigenschaften. Diese können außer der Position außer der Position überschrieben werden, bei der sich einzelne Shapes nicht ändern können.
Die Drehungsmethode kann überschrieben werden, wie in der Circle-Klasse, die aufgrund ihrer Symmetrie drehungsinvariant ist. Daher wird die Drehungsmethode in der Circle-Klasse durch eine Methode ersetzt, die nichts tut.
// An abstract class that has some methods and properties defined
// and some left abstract.
[<AbstractClass>]
type Shape2D(x0: float, y0: float) =
let mutable x, y = x0, y0
let mutable rotAngle = 0.0
// These properties are not declared abstract. They
// cannot be overriden.
member this.CenterX
with get () = x
and set xval = x <- xval
member this.CenterY
with get () = y
and set yval = y <- yval
// These properties are abstract, and no default implementation
// is provided. Non-abstract derived classes must implement these.
abstract Area: float with get
abstract Perimeter: float with get
abstract Name: string with get
// This method is not declared abstract. It cannot be
// overridden.
member this.Move dx dy =
x <- x + dx
y <- y + dy
// An abstract method that is given a default implementation
// is equivalent to a virtual method in other .NET languages.
// Rotate changes the internal angle of rotation of the square.
// Angle is assumed to be in degrees.
abstract member Rotate: float -> unit
default this.Rotate(angle) = rotAngle <- rotAngle + angle
type Square(x, y, sideLengthIn) =
inherit Shape2D(x, y)
member this.SideLength = sideLengthIn
override this.Area = this.SideLength * this.SideLength
override this.Perimeter = this.SideLength * 4.
override this.Name = "Square"
type Circle(x, y, radius) =
inherit Shape2D(x, y)
let PI = 3.141592654
member this.Radius = radius
override this.Area = PI * this.Radius * this.Radius
override this.Perimeter = 2. * PI * this.Radius
// Rotating a circle does nothing, so use the wildcard
// character to discard the unused argument and
// evaluate to unit.
override this.Rotate(_) = ()
override this.Name = "Circle"
let square1 = new Square(0.0, 0.0, 10.0)
let circle1 = new Circle(0.0, 0.0, 5.0)
circle1.CenterX <- 1.0
circle1.CenterY <- -2.0
square1.Move -1.0 2.0
square1.Rotate 45.0
circle1.Rotate 45.0
printfn "Perimeter of square with side length %f is %f, %f" (square1.SideLength) (square1.Area) (square1.Perimeter)
printfn "Circumference of circle with radius %f is %f, %f" (circle1.Radius) (circle1.Area) (circle1.Perimeter)
let shapeList: list<Shape2D> = [ (square1 :> Shape2D); (circle1 :> Shape2D) ]
List.iter (fun (elem: Shape2D) -> printfn "Area of %s: %f" (elem.Name) (elem.Area)) shapeList
Ausgabe:
Perimeter of square with side length 10.000000 is 40.000000
Circumference of circle with radius 5.000000 is 31.415927
Area of Square: 100.000000
Area of Circle: 78.539816