最簡單的三個類
public class Animal { public Animal() { Debug.Log("Construct Animal!"); } }
public class Mammal : Animal { public Mammal() { Debug.Log("Construct Mamal!"); } }
public class Sheep : Mammal { public Sheep() { Debug.Log("Construct Sheep!"); } }
Sheep sheep = new Sheep();
子類的構造函數會依次執行基類的構造函數,沒有異議。
需要注意的是,沒有特別聲明,子類都會自動去找父類中沒有參數的構造函數,如果基類中沒有,則需要在子類的構造函數中調用,比如:
public class Animal{ int age; public Animal(int _age) { age = _age; Debug.Log("Construct Animal!"); } }
public Mammal():base(0) { Debug.Log("Construct Mamal!"); }
在基類Animal中添加函數
public void Eat() { Debug.Log("Animal Eat!"); }
下面談一下方法的覆蓋
在子類Sheep中覆蓋定義Eat方法
public new void Eat() { Debug.Log("Sheep Eat!"); }
new 關鍵字可以顯式隱藏從基類繼承的成員。隱藏繼承的成員時,該成員的派生版本將替換基類版本。雖然可以不使用 new 修飾符來隱藏成員,但將收到編譯器警告。如果使用 new 來顯式隱藏成員,將禁止此警告。
測試代碼:
Sheep sheep = new Sheep(); Animal animal = new Sheep(); sheep.Eat(); animal.Eat();
沒有發生多態行為,聲明的基類對象,執行的就是基類方法,聲明的子類對象,執行的就是子類方法。
在子類的函數中,都有一個base變量,可以認為是一個對基類的引用,通過base就可以調用基類的方法。
多態就是多態就是父類引用指向子類對象,調用方法時會調用子類的實現,而不是父類的實現,這叫多態。
基類Animal中定義函數
public virtual void Birth() { Debug.Log("Animal Birth!"); }
Sheep中overrride一下
public override void Birth() { Debug.Log("Sheep Birth!"); }
Sheep sheep = new Sheep(); Animal animal = new Sheep(); animal.Birth();
有下面兩個需要注意的點
1.子類調用父類的方法
當然是直接用base了。
2.繼承鏈中的虛方法
無論在虛擬成員和最初聲明虛擬成員的類之間已聲明了多少個類,虛擬成員永遠都是虛擬的。如果類 A 聲明了一個虛擬成員,類 B 從 A 派生,類 C 從類 B 派生,則類 C 繼承該虛擬成員,並且可以選擇重寫它,而不管類 B 是否為該成員聲明了重寫。
Sealed關鍵字的用法
Sealed關鍵字用來阻止派生類重寫虛擬成員。還是舉例說明。
基類Animal中定義方法
public virtual void Move() { Debug.Log("Animal Move!"); }
public sealed override void Move() { Debug.Log("Mammal Move!"); }
public new void Move() { Debug.Log("Sheep Move!"); }
寫點代碼來測試多態性
Animal animal = new Animal(1); Animal animal1 = new Mammal(1); Animal animal2 = new Sheep(); Sheep sheep = new Sheep(); animal.Move(); animal1.Move(); animal2.Move(); sheep.Move();
第一個無話可說,直接執行了Animal的move函數
第二個,正常的多態
第三個有點意思,多態到Mammal就打住了
第四個就是普通的執行Sheep類的成員函數。
abstract關鍵字的使用
官方解釋:abstract 修飾符指示所修飾的內容缺少實現或未完全實現。abstract 修飾符可用於類、方法、屬性、索引器和事件。在類聲明中使用 abstract 修飾符以指示某個類只能是其他類的基類。標記為抽象或包含在抽象類中的成員必須通過從抽象類派生的類來實現。
接地氣的解釋:abstract類用於搭建子類的框架,子類必須實現其中的abstract方法,使用的也是override關鍵字。
abstract方法和vitual方法的區別
abstract方法沒有函數體,子類一定要有對應方法的實現。
vitual方法子類可以選擇實現也可以選擇不實現。
兩個都可以用於實現多態。
抽象類不能實例化。抽象類的用途是提供一個可供多個派生類共享的通用基類定義。例如,類庫可以定義一個抽象類,將其用作多個類庫函數的參數,並要求使用該庫的程序員通過創建派生類來提供自己的類實現。
接口包含類或結構可以實現的一組相關功能的定義。
例如,使用接口可以在類中包括來自多個源的行為。 由於C#語言不支持多重繼承,所以該功能很重要。 此外,如果要模擬結構的繼承,也必須使用接口,因為它們無法實際從另一個結構或類繼承。
定義一個簡單的接口,只有接口函數的定義,沒有實現。
public interface ISay { void SayHello(); void SayFuck(); }
Sheep繼承ISay接口
public class Sheep : Mammal, ISay
public void SayHello() { Debug.Log("ISay Hello"); } public void SayFuck() { Debug.Log("ISay SayFuck"); }
Sheep sheep = new Sheep(); sheep.SayHello(); sheep.SayFuck();
接口有下面幾個屬性
接口類似於抽象基類。實現接口的任何類或結構都必須實現其所有成員。
接口無法直接進行實例化。其成員由實現接口的任何類或結構來實現。
接口可以包含事件、索引器、方法和屬性。
接口不包含方法的實現。
一個類或結構可以實現多個接口。一個類可以繼承一個基類,還可實現一個或多個接口。
MSDN