Klasy abstrakcyjne (F#)
Klasy abstrakcyjne są klasy, które opuszczają niektórych lub wszystkich członków niezaimplementowane, tak aby implementacji może być udostępniane przez klas pochodnych.
// 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
Uwagi
W programowaniu zorientowanym obiektowo, klasa abstrakcyjna służy jako klasa podstawowa hierarchii i stanowi często używane funkcje zestaw typów obiektów.Jak sugeruje nazwa "abstract", klasy abstrakcyjne często nie odpowiadają bezpośrednio na konkretne podmioty w domenie problem.Jednak stanowią one co wielu różnych podmiotów konkretnych mają wspólne.
Abstrakcyjne klasy musi mieć AbstractClass atrybut.Można mieć zaimplementowany i niezaimplementowane członków.Użycie terminu abstrakcyjna po zastosowaniu do klasy jest taka sama, jak w innych.Języki netto; Jednak użycie terminu abstrakcyjna po zastosowaniu metod (i właściwości) jest nieco inny w F# z jego stosowania w innych.Języki netto.F#, gdy metoda jest oznaczona z abstract słowa kluczowego, to wskazuje, że członek ma wpis, znany jako wirtualnych wysyłki gniazdo, w wewnętrznej tabeli wirtualnej funkcji dla tego typu.Innymi słowy, metoda jest wirtualna, chociaż virtual słowo kluczowe nie jest używana w języku F#.Słowo kluczowe abstract jest używana w metodach wirtualnych, niezależnie od tego, czy metoda została zaimplementowana.Deklarację gniazdo wirtualnego wysyłki jest niezależna od definicji metody dla tego gniazda wysyłki.W związku z tym F# równoważna metoda wirtualna deklaracji i definicji w innym.Język netto jest kombinacją zarówno deklarację metoda abstrakcyjna i odrębnej definicji, z albo default słowa kluczowego lub override słowa kluczowego.Aby uzyskać dodatkowe informacje i przykłady, zobacz Metody (F#).
Klasa jest uważany za abstrakcyjne tylko wtedy, gdy istnieją metody abstrakcyjne zadeklarowana, ale nie jest zdefiniowany.W związku z tym klasami, które zawierają metody abstrakcyjne nie są koniecznie abstrakcyjne klasy.Nie należy używać, chyba że klasa zawiera niezdefiniowane metody abstrakcyjne, AbstractClass atrybut.
In the previous syntax, accessibility-modifier can be public, private or internal.Aby uzyskać więcej informacji, zobacz Kontrola dostępu (F#).
Podobnie jak w przypadku innych typów klasy abstrakcyjne może mieć klasy podstawowej i jednym lub kilkoma oprzeć interfejsów.Każda klasa podstawowa lub interfejsu pojawia się w osobnym wierszu, wraz z inherit słowa kluczowego.
Definicja typu klasy abstrakcyjnej mogą zawierać członków zdefiniowanych w pełni, ale może również zawierać członków abstrakcyjny.Składni abstrakcyjnej członków oddzielnie pokazano składnię poprzedniego.W tej składni type signature członka jest lista, która zawiera parametr typy w kolejności i zwracanych typów oddzielone -> tokenów i/lub * tokeny odpowiednio dla curried i tupled parametry.Składnia abstrakcyjnego członka typu podpisów jest taka sama, jak używane w plikach podpisu oraz wykazane, przez technologię IntelliSense w edytorze kodu Visual Studio.
Przykład
Poniższy kod ilustruje klasa abstrakcyjna Shape, który ma dwie klasy pochodnej nieabstrakcyjna, Square i Circle.W przykładzie przedstawiono sposób korzystania z klasy abstrakcyjne, metod i właściwości.Na przykład klasa abstrakcyjna Shape reprezentuje wspólne elementy konkretne podmioty circle i square.Wspólne cechy wszystkich kształtów (w dwuwymiarowym układzie współrzędnych) są wydobywane out do Shape klasy: pozycji na siatce, kąt obrotu i właściwości powierzchni i obwodu.Te może zostać zastąpiona, z wyjątkiem pozycji, zachowanie, którego nie można zmienić poszczególne kształty.
Metoda obrót może zostać zastąpiona, jak w Circle klasy, która jest niezmienny rotacji z powodu jego symetrii.Tak w Circle klasy, metody obracania zastępuje metodę, że nic nie robi.
// 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
// overriden.
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