C# 物件導向說明

      在〈C# 物件導向說明〉中尚無留言

類別宣告

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 : 全部都有效

permission

繼承後之建構子

在下述之程式碼中, 執行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 (又一經典的腦殘設計)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *