共用方式為


抽象類

抽象類 是讓部分或所有成員未實作的類別,因此衍生類別可以提供實作。

語法

// 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

備註

在面向物件程序設計中,抽象類會當做階層的基類使用,並代表各種物件類型的常見功能。 正如「抽象」名稱所暗示,抽象類通常不會直接對應到問題域中的具體實體。 不過,它們確實代表許多不同實體的共同點。

抽象類必須具有 AbstractClass 屬性。 它們可以實作和未實作的成員。 套用至類別時,使用 抽象 詞彙與其他 .NET 語言相同;不過,當套用至方法 (和 屬性) 時,使用 抽象 一詞與在其他 .NET 語言中的用法稍有不同。 在 F# 中,當方法以 abstract 關鍵詞標記時,這表示成員在該類型的虛擬函式內部數據表中具有稱為 虛擬分派位置的專案。 換句話說,雖然 F# 中未使用 關鍵詞, virtual 但方法是虛擬的。 不論是否實作 方法,都會在虛擬方法上使用 關鍵詞 abstract 。 虛擬分派位置的宣告與該分派位置的方法定義不同。 因此,另一種 .NET 語言中虛擬方法宣告和定義的 F# 對等專案,是抽象方法宣告和個別定義的組合,具有 default 關鍵詞或 override 關鍵詞。 如需詳細資訊和範例,請參閱 方法

只有在有宣告但未定義的抽象方法時,才會將類別視為抽象。 因此,具有抽象方法的類別不一定是抽象類。 除非類別具有未定義的抽象方法,否則請勿使用 AbstractClass 屬性。

在先前的語法中, 輔助功能修飾詞 可以是 publicprivateinternal。 如需詳細資訊,請參閱 存取控制

如同其他類型,抽象類可以有基類和一或多個基底介面。 每個基類或介面都會與 inherit 關鍵詞一起出現在個別行上。

抽象類的類型定義可以包含完整定義的成員,但它也可以包含抽象成員。 抽象成員的語法會分別顯示在上一個語法中。 在此語法中,成員 的類型簽章 是一個清單,其中包含依序排列的參數類型和傳回型別,根據捲曲和 Tupled 參數,以 -> 標記和/或 * 標記分隔。 抽象成員類型簽章的語法與在簽章檔案中使用的語法相同,以及 IntelliSense 在 Visual Studio Code 編輯器中顯示的語法。

下列程式代碼說明抽象類 Shape,其具有兩個非抽象衍生類別 Square 和 Circle。 此範例示範如何使用抽象類、方法和屬性。 在範例中,抽象類 Shape 代表具體實體圓形和方形的通用元素。 所有圖形的通用特徵(在二維座標系統中)都會抽象化成 Shape 類別:網格線上的位置、旋轉角度,以及區域和周邊屬性。 這些可以覆寫,但位置除外,個別圖形無法變更的行為。

旋轉方法可以覆寫,如同 Circle 類別中一樣,因為其對稱性而旋轉不變。 因此,在 Circle 類別中,旋轉方法會由不執行任何動作的方法取代。

// 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

輸出:

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

另請參閱