類別宣告
class Pokemon { public float w, h; public Pokemon() { } }
物件變數存取權限
public : 可由其他類別及物件存取
private : 僅允許自身類別存取
建構子
需為public, 才可由其他類別new 出物件. 若為private , 則為singletone的設計模式
若無自訂建構子, 編譯器會自動加上預設建構子
若加入自訂建構子, 編譯器不會自動加上預設建構子
建構子覆寫
建構子覆寫後, 需要由A建構子呼叫B建構子, 則是於A建構子後面加上 “:” , 如下所示
class Pokemon
{
float w, h;
public Pokemon() : this (10.0f, 0.1f)
{
Console.WriteLine("原始 Pokemon 出生了");
}
public Pokemon(float w, float h)
{
Console.WriteLine("自訂 Pokemon 出生了");
this.w = w;
this.h = h;
}
}
類別繼承
類別繼承, 於class後面加上 “:”, 如下所示
class Pokemon { public float w, h; } class Pikachu : Pokemon{} } class Eve : Pokemon{}
此時的Pikachu及 Eve都會繼承了Pokemon的w, h物件變數
繼承後的存取修飾子
private : 只允許在同類別內存取
protected : 類別及子類別有效, 不同namespace之子類別也有效. 但同namespace內, 物件無效
internal : 同namespace有效
protected internal : 同namespace及不同namespace之子類別有效
public : 全部都有效
繼承後之建構子
在下述之程式碼中, 執行new Pikachu()後,竟會出現
Pokemon出生
皮卡丘出生
class Pokemon { public float w, h; public Pokemon() { Console.WriteLine("Pokemon出生"); } } class Pikachu : Pokemon{ public Pikachu() { Console.WriteLine("皮卡丘出生"); } }
皮卡丘出生, 跟Pokemon有什麼關係呢? 原來在執行子類別建構子時, 編譯器會自動在public Pikachu()後面加上 : base(). 所以會先執行父類別建構子, 再執行子類別建構子
public Pikachu():base()
{
Console.WriteLine("皮卡丘出生");
}
那問題又來了, 如果父類別是自訂建構子呢? 此時編譯器不會幫父類別加預設建構子, 所以子類別就會出錯了. 此時不是在父類別自己手動加預設建構子, 不然就是在子類別建構子加上
” : base(xxx, xxx)”
class Pokemon { public float w, h; public Pokemon() { } //自己加預設建構子 public Pokemon(float w, float h) { Console.WriteLine("Pokemon出生"); this.w = w; this.h = h; } } class Pikachu : Pokemon{ public Pikachu():base(10.0f, 0.3f) { Console.WriteLine("皮卡丘出生"); } }
abstract class
當在Main()中, new Pokemon(), 其實是無意義的, 也就是說, 要嘛就new 皮卡丘, 不然就new Eve(). 所以產生一隻Pokemon(), 是什麼鬼啊. 所以為了讓Pokemon()生不出物件, 就可以在class Pokemon前加上abstract
abstract class Pokemon { public float w, h; protected int level; abstract public void setLevel(int x); } class Pikachu : Pokemon{ public override void setLevel(int l) { level = 10; } }
特別注意二件事
1. 在父類別內若有抽像方法, 方法需宣告變數名稱, 而子類別實作時, 不需要用相同的變數名稱
abstract public void setLevel(int x); //真是腦殘的設計啊
2. 子類別實作類別後, 一樣是使用 “:”, 而方法實作時, 需加上override
public override void setLevel(int l); //又是一個腦殘的設計
interface
介面, 是用來規範類別具備那一種類, 或屬於那一種族群的作法, 如下程式碼說明完整的介面操作
interface Swing { void setSwing(); } interface Running { void setRunning(); } abstract class Pokemon:Swing, Running { public float w, h; protected int level; abstract public void setRunning(); public void setSwing() { Console.WriteLine("會游泳"); } } class Pikachu : Pokemon{ public Pikachu() { setSwing(); setRunning(); } public override void setRunning() { Console.WriteLine("會跑步"); } }
介面宣告後, 裏面不可以有實作的方法, 這跟一般的物件導向一樣
父類別Pokemon實作介面時, 一樣是用 “:” 繼承, 而且可以多個實作, 中間用 “,”分開
class Pokemon:Swing, Running
當Pokemon實作了介面後, 若不想實作抽像方法, 並不是在類別前加上abstract class就能了事的, 還必需在類別內宣告介面的抽像方法 abstract public void setRunning(); 然後再於子類別實作並override (又一經典的腦殘設計)