- F# 基礎教程
- F# - 首頁
- F# - 概述
- F# - 環境搭建
- F# - 程式結構
- F# - 基本語法
- F# - 資料型別
- F# - 變數
- F# - 運算子
- F# - 決策
- F# - 迴圈
- F# - 函式
- F# - 字串
- F# - 可選型別
- F# - 元組
- F# - 記錄
- F# - 列表
- F# - 序列
- F# - 集合
- F# - 對映
- F# - 判別聯合
- F# - 可變資料
- F# - 陣列
- F# - 可變列表
- F# - 可變字典
- F# - 基本輸入輸出
- F# - 泛型
- F# - 委託
- F# - 列舉
- F# - 模式匹配
- F# - 異常處理
- F# - 類
- F# - 結構體
- F# - 運算子過載
- F# - 繼承
- F# - 介面
- F# - 事件
- F# - 模組
- F# - 名稱空間
F# - 繼承
面向物件程式設計中最重要的概念之一是繼承。繼承允許我們根據另一個類來定義一個類,這使得建立和維護應用程式變得更容易。這也提供了重用程式碼功能和加快實現時間的機會。
在建立類時,程式設計師可以指定新類應該繼承現有類的成員,而不是完全編寫新的資料成員和成員函式。這個現有的類稱為基類,新類稱為派生類。
繼承的概念實現了 IS-A 關係。例如,哺乳動物 IS A 動物,狗 IS-A 哺乳動物,因此狗 IS-A 動物,依此類推。
基類和子類
子類派生自已定義的基類。子類繼承基類的成員,並擁有自己的成員。
子類使用inherit關鍵字定義,如下所示:
type MyDerived(...) = inherit MyBase(...)
在 F# 中,一個類最多隻能有一個直接基類。如果未使用inherit關鍵字指定基類,則該類隱式地繼承自 Object。
請注意:
基類的的方法和成員對派生類的使用者可用,就像派生類的直接成員一樣。
let 繫結和建構函式引數對類是私有的,因此無法從派生類訪問。
關鍵字base指的是基類例項。它像 self 識別符號一樣使用。
示例
type Person(name) =
member x.Name = name
member x.Greet() = printfn "Hi, I'm %s" x.Name
type Student(name, studentID : int) =
inherit Person(name)
let mutable _GPA = 0.0
member x.StudentID = studentID
member x.GPA
with get() = _GPA
and set value = _GPA <- value
type Teacher(name, expertise : string) =
inherit Person(name)
let mutable _salary = 0.0
member x.Salary
with get() = _salary
and set value = _salary <- value
member x.Expertise = expertise
//using the subclasses
let p = new Person("Mohan")
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")
p.Greet()
st.Greet()
tr.Greet()
編譯並執行程式後,它將產生以下輸出:
Hi, I'm Mohan Hi, I'm Zara Hi, I'm Mariam
重寫方法
您可以重寫基類方法的預設行為,並在子類或派生類中以不同的方式實現它。
預設情況下,F# 中的方法不可重寫。
要在派生類中重寫方法,必須使用abstract和default關鍵字將方法宣告為可重寫,如下所示:
type Person(name) = member x.Name = name abstract Greet : unit -> unit default x.Greet() = printfn "Hi, I'm %s" x.Name
現在,Person 類的Greet方法可以在派生類中重寫。以下示例演示了這一點:
示例
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
default x.Greet() = printfn "Hi, I'm %s" x.Name
type Student(name, studentID : int) =
inherit Person(name)
let mutable _GPA = 0.0
member x.StudentID = studentID
member x.GPA
with get() = _GPA
and set value = _GPA <- value
override x.Greet() = printfn "Student %s" x.Name
type Teacher(name, expertise : string) =
inherit Person(name)
let mutable _salary = 0.0
member x.Salary
with get() = _salary
and set value = _salary <- value
member x.Expertise = expertise
override x.Greet() = printfn "Teacher %s." x.Name
//using the subclasses
let p = new Person("Mohan")
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")
//default Greet
p.Greet()
//Overriden Greet
st.Greet()
tr.Greet()
編譯並執行程式後,它將產生以下輸出:
Hi, I'm Mohan Student Zara Teacher Mariam.
抽象類
有時需要提供物件的非完整實現,該實現實際上不應該被實現。稍後,其他程式設計師應該建立抽象類的子類以完成實現。
例如,在學校管理系統中不需要 Person 類。但是,需要 Student 或 Teacher 類。在這種情況下,可以將 Person 類宣告為抽象類。
AbstractClass屬性告訴編譯器該類有一些抽象成員。
無法建立抽象類的例項,因為該類未完全實現。
以下示例演示了這一點:
示例
[<AbstractClass>]
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
type Student(name, studentID : int) =
inherit Person(name)
let mutable _GPA = 0.0
member x.StudentID = studentID
member x.GPA
with get() = _GPA
and set value = _GPA <- value
override x.Greet() = printfn "Student %s" x.Name
type Teacher(name, expertise : string) =
inherit Person(name)
let mutable _salary = 0.0
member x.Salary
with get() = _salary
and set value = _salary <- value
member x.Expertise = expertise
override x.Greet() = printfn "Teacher %s." x.Name
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")
//Overriden Greet
st.Greet()
tr.Greet()
編譯並執行程式後,它將產生以下輸出:
Student Zara Teacher Mariam.