F#繼承

2018-12-16 14:04 更新

面向?qū)ο缶幊讨凶钪匾母拍钪皇抢^承。 繼承允許我們根據(jù)另一個(gè)類來(lái)定義一個(gè)類,這使得創(chuàng)建和維護(hù)應(yīng)用程序更容易。 這也提供了重用代碼功能和快速實(shí)現(xiàn)時(shí)間的機(jī)會(huì)。
在創(chuàng)建類時(shí),程序員可以指定新類應(yīng)該繼承現(xiàn)有類的成員,而不是編寫完全新的數(shù)據(jù)成員和成員函數(shù)。 這個(gè)現(xiàn)有類稱為基類,新類稱為派生類。
繼承的想法實(shí)現(xiàn)IS-A關(guān)系。 例如,哺乳動(dòng)物ISA動(dòng)物,狗IS-A哺乳動(dòng)物,因此也是狗IS-A動(dòng)物等。

基類和子類

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

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

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

請(qǐng)注意

基類的方法和成員對(duì)派生類的用戶是可用的,就像派生類的直接成員一樣。
讓綁定和構(gòu)造函數(shù)參數(shù)對(duì)類是私有的,因此不能從派生類訪問(wèn)。
關(guān)鍵字base是指基類實(shí)例。 它像自標(biāo)識(shí)符一樣使用。

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

當(dāng)你編譯和執(zhí)行程序,它產(chǎn)生以下輸出 

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

重載方法

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

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

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

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

當(dāng)你編譯和執(zhí)行程序,它產(chǎn)生以下輸出 

Hi, I'm Mohan
Student Zara
Teacher Mariam.

抽象類

有時(shí)你需要提供一個(gè)不完整的實(shí)現(xiàn)對(duì)象,這不應(yīng)該在現(xiàn)實(shí)中實(shí)現(xiàn)。 后來(lái),一些其他程序員應(yīng)該創(chuàng)建抽象類的子類來(lái)完成實(shí)現(xiàn)。
例如,在學(xué)校管理系統(tǒng)中將不需要Person類。 但是,需要學(xué)生或教師課。 在這種情況下,您可以將Person類聲明為抽象類。
AbstractClass屬性告訴編譯器該類有一些抽象函數(shù)。
您不能創(chuàng)建抽象類的實(shí)例,因?yàn)樵擃愇赐耆珜?shí)現(xiàn)。
下面的例子演示了這個(gè) 

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

當(dāng)你編譯和執(zhí)行程序,它產(chǎn)生以下輸出 

Student Zara
Teacher Mariam.
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)