F#繼承

2018-12-16 14:04 更新

面向對象編程中最重要的概念之一是繼承。 繼承允許我們根據另一個類來定義一個類,這使得創(chuàng)建和維護應用程序更容易。 這也提供了重用代碼功能和快速實現(xiàn)時間的機會。
在創(chuàng)建類時,程序員可以指定新類應該繼承現(xiàn)有類的成員,而不是編寫完全新的數據成員和成員函數。 這個現(xiàn)有類稱為基類,新類稱為派生類。
繼承的想法實現(xiàn)IS-A關系。 例如,哺乳動物ISA動物,狗IS-A哺乳動物,因此也是狗IS-A動物等。

基類和子類

子類是從已定義的基類派生的。 一個子類繼承了基類的成員,并且有自己的成員。
子類是使用inherit關鍵字定義的,如下所示 

type MyDerived(...) =
   inherit MyBase(...)

在F#中,一個類最多只能有一個直接基類。如果你不使用inherit關鍵字指定基類,這個類隱含從Object繼承。

請注意

基類的方法和成員對派生類的用戶是可用的,就像派生類的直接成員一樣。
讓綁定和構造函數參數對類是私有的,因此不能從派生類訪問。
關鍵字base是指基類實例。 它像自標識符一樣使用。

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()

當你編譯和執(zhí)行程序,它產生以下輸出 

Hi, I'm Mohan
Hi, I'm Zara
Hi, I'm Mariam

重載方法

您可以覆蓋基類方法的默認行為,并在子類或派生類中以不同方式實現(xiàn)它。
默認情況下,F(xiàn)#中的方法不可重寫。
要覆蓋派生類中的方法,必須使用abstractdefault關鍵字將方法聲明為可覆蓋,如下所示:

type Person(name) =
   member x.Name = name
   abstract Greet : unit -> unit
   default x.Greet() = printfn "Hi, I'm %s" x.Name

現(xiàn)在,Person類的問候方法可以在派生類中重寫。下面的例子說明了這一點 

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()

當你編譯和執(zhí)行程序,它產生以下輸出 

Hi, I'm Mohan
Student Zara
Teacher Mariam.

抽象類

有時你需要提供一個不完整的實現(xiàn)對象,這不應該在現(xiàn)實中實現(xiàn)。 后來,一些其他程序員應該創(chuàng)建抽象類的子類來完成實現(xiàn)。
例如,在學校管理系統(tǒng)中將不需要Person類。 但是,需要學生或教師課。 在這種情況下,您可以將Person類聲明為抽象類。
AbstractClass屬性告訴編譯器該類有一些抽象函數。
您不能創(chuàng)建抽象類的實例,因為該類未完全實現(xiàn)。
下面的例子演示了這個 

[<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()

當你編譯和執(zhí)行程序,它產生以下輸出 

Student Zara
Teacher Mariam.
以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號