共用方式為


抽象類別 (F#)

「抽象類別」(Abstract Class) 是使部分或全部成員保持未實作狀態的類別,因此衍生類別可以提供實作。

// 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 屬性。 它們可以有已實作和未實作的成員。 「抽象」(Abstract) 一詞的用法在套用至類別時與其他 .NET 語言相同;不過,在 F# 中,「抽象」(Abstract) 一詞的用法在套用至方法 (和屬性) 時與其他 .NET 語言稍有不同。 在 F# 中,當方法以 abstract 關鍵字標記時,這表示成員在該型別的內部虛擬函式資料表中有項目,稱為「虛擬分派位置」(Virtual Dispatch Slot)。 換句話說,方法為虛擬,儘管 F# 語言中不使用 virtual 關鍵字。 無論是否實作方法,虛擬方法上都會使用 abstract 關鍵字。 虛擬分派位置的宣告與該分派位置的方法定義是分開的。 因此,另一個 .NET 語言的虛擬方法宣告和定義,其 F# 對等用法為抽象方法宣告和分開定義的組合,並且具有 default 關鍵字或 override 關鍵字。 如需詳細資訊與範例,請參閱方法 (F#)

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

在上述語法中,accessibility-modifier 可以是 public、private 或 internal。 如需詳細資訊,請參閱存取控制 (F#)

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

抽象類別的型別定義可以包含完整定義成員,也可以包含抽象成員。 在上述語法中,個別顯示抽象成員的語法。 在這個語法中,成員的 type signature 是包含依序排列參數型別和傳回型別的清單,型別之間根據局部調用和 Tuple 參數以 -> 語彙基元和 (或) * 語彙基元分隔。 抽象成員型別簽章的語法與簽章檔案中所使用的語法以及 Visual Studio 程式碼編輯器中 IntelliSense 所顯示的語法相同。

範例

下列程式碼說明有兩個非抽象衍生類別 Square 和 Circle 的抽象類別 Shape。 此範例示範如何使用抽象類別、方法和屬性。 在範例中,抽象類別 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
    // 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
  

請參閱

參考

類別 (F#)

方法 (F#)

屬性 (F#)

概念

成員 (F#)