close

重點1. 類別如何使用繼承之特性(以動物為例)

step1:

尋找所有動物接有的共通事物

 1  

step2:

依step1所歸納出之特性,建立一個superclass,提供所有動物的共同特質

 2  

step3:

判斷每一種動物與superclass所提供的方法有何不同?

1.也就是說當你繼承superclass時雖然必須繼承他所有行為,但是你可以進行覆寫(當你的subclass與superclass方法同名,但執行之行為不同時)。

2.當沒有同名方法時,subclass也可以撰寫自己的方法。

 3  

step4:

尋找擁有許多共通特質之類別

貓,老虎,獅子都屬於貓科,所以我們可以在這三個class上再加上一個Feline(貓科動物)

 4    

step5:

依step4方式建構自己的類別階層結構。

 5  

以上步驟做完的好處

1.避免重複之程式碼

2.程式碼變得容易理解以及維護(例如當你在看Feline類別時,你就知道你正在看所有貓科動物的共同特質)。

這與傳統沒有物件導向的程式設計師寫出來的程序導向程式,會差非常多,主要在於debug光是程式跑到這裡是在幹嘛,都會弄個一兩個小時也不誇張。

 

重點2 :子類別可以覆寫方法,改變或取代他繼承之方法。

有時侯子類別想從覆類別繼承到大多數的方法,但是不是全部,當子類別想要改變繼承到的方法時,可以使用Override

如何使用?

Step1:

class Bird

{

public virtual void Fly()

{response.write("I can Fly.")}

}

 

class Penguin : Bird

{

public override void Fly()

{

response.write("i can not fly.")

}

}

note: 覆蓋掉Fly(),注意此覆類別方法沒有回傳值且沒有參數,所以子類別也要是void且沒有參數。

 

重點3 : 子類別之instance不可以指派給父類別。

ex:

Sandwich 為 BLT 之父類別。

Sandwich mySandwich  = new Sandwich();

BLT myBlt  = new BLT();

Sandwich someSandwich = myBlt // 正確可以將myBlt指定給任何Snadwich之變數。

BLT anotherBLT = mySandwich; //編譯失敗,並非所有BLT都是Sandwich

 

重點4: Shadow(遮蔽) 

  1. Public class BaseClass  
  2. {  
  3.    //注意這裡沒有使用 virtual 關鍵字
  4.     public string GetMethodOwnerName()  
  5.     {  
  6.        return "Base Class";  
  7.     }  
  8. }
  9.   
  10. public class ChildClass : BaseClass  
  11. {  
  12.     //注意這裡的 new 關鍵字
  13.     public new string GetMethodOwnerName()  
  14.     {  
  15.        return "ChildClass";  
  16.     }  
  17. }  

 

 

  1. static void Main(string[] args)  
  2. {  
  3.     ChildClass c = new ChildClass();  
  4.     Console.WriteLine(c.GetMethodOwnerName());  
  5. }  

   

    OutPut : ChildClass

 

   當父class沒有使用 virtual 關鍵字,而子類別要使用 new 關鍵字時,會將父類別的同名方法給遮蔽掉。

   與override非常相似,但是撰寫程式時我們不會事先知道那些要加override,所以也可用此種方式萬一父class沒加 virtual,可以在子class加上new,達到覆蓋同效果。

   

重點5 : 方法多載(overloading)

假設希望一個Car3 class中能有多種加速方式,如下:

Accelerate();

Accelerate(50);

Accelerate("STOP");

因為上述Accelerate方法參數個數與資料型別不同,所以可以使用overloading來達成

ex.

Car3 class 檔案: 

public class Car3
{
private int speed = 0;
public int Speed
{
get { return speed; }
set
{
if (value <= 0)
speed = 0;
if (value > 1)
speed = 200;
}
}

public void Accelerate()
{
this.Speed++;
}

public void Accelerate(int addSpeed)
{
this.Speed += addSpeed;
}

public void Accelerate(String s)
{
if (s == "STOP") this.Speed = 0;
}
}

 

.cs檔案:

protected void Page_Load(object sender, EventArgs e)
{
Car3 Benz = new Car3();
Response.Write("現在速度:"+Benz.Speed);
Benz.Accelerate();
Response.Write("現在速度:" + Benz.Speed);
Benz.Accelerate(10);
Response.Write("現在速度:" + Benz.Speed);
Benz.Accelerate("STOP");
Response.Write("現在速度:" + Benz.Speed);
}

結果:  現在速度:0現在速度:0現在速度:200現在速度:0

 

note: 比較多載(overloading)與覆寫(overriding)

多載成員: 可以接受不同個數之參數或不同資料型別之參數,用來提供不同版本的屬性或方法

覆寫成員: 子類別之成員可以取代父類別中不適用之成員,子類別覆寫父類別之成員時,子類別和父類別之成員必須接受相同個數參數與相同資料型別

 

重點.6 動態繫結(Dynamic Binding)(多型)

Dynamic binding是程式進入執行階段時,物件參考才決定所要執行之方法,其做法是父類別的物件參考來選擇所要執行之子類別物件實體方法,透過此法達到多型

ex.

Traffic class 有兩個子類別為 Car 以及 Airplane,當輸入1時 Traffic 之參考 r 會去指向Car名為myCar之實體物件,而當輸入2時 r 會去指向Airplane之物件myAirplane

 

superclass 檔案:

public class Traffic
{
protected static string Name;
public virtual string SpeedUp() {return "father"; }
}

 

Car class檔案:

public class Car : Traffic
{
public override string SpeedUp()
{
Name = "我是車子";
return Name;
}
}

 

Airplane class 檔案:

public class Airpalne:Traffic
{
public override string SpeedUp()
{
Name = "我是飛機";
return Name;
}
}

 

.cs檔案(前端請拉一個textbox跟button即可)

protected void Button1_Click(object sender, EventArgs e)
{
Traffic r; // r為Traffic類別之參考
Car myCar = new Car();
Airpalne myAirplane = new Airpalne();
string input = TextBox1.Text;
if (input == "1")
{
r = myCar; //如果tetxbox輸入為1,r指向myCar物件實體
}
else if (input == "2")
{
r = myAirplane;
}
else {
return;
}
Response.Write(r.SpeedUp()); //看輸入之值決定去呼叫哪一個類別之SpeedUp()
}

結論: 

父類別之參考可以動態指向同一類別或子類別之物件實體,進而操作參考所指向之實體方法或屬性,稱之多型

例如上述 r 指向 myCar 物件實體,則 r 可以操作 myCar物件和 r 相同之屬性或方法

 

7.子類別用base關鍵字存取其父類別

假設A class 為 B class 之 父類別。

 

A的成員變數與方法如下:

1.成員變數: NumberOfLegs

2.方法: Eat(), Swallow(), Diget()

 

B的成員變數與方法如下:

1.成員變數: TongueLength

2.方法: CatchWithTongue()

 

ex.

class A

{

  public virtual void Eat(Food morsel)

  {

      Swallow(morsle);

      Digest();

  }

}

 

//較長的寫法

calss B : A

{

  public override void Eat(Food morsel)

  {

      CatchWithFood(morsel); //較父類別多了這個

      Swallow(morsel);

      Digest();

  }

}

可以改成下列寫法:

class B : A

{

 public override void Eat(Food morsel)

  {

      CatchWithFood(morsel);

      base.Eat(morsel); //因為父類別的Eat()包含Swallow(morsel) and  Digest(),所以利用base關鍵字可以使用覆類別之方法。

  }

}

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 melomelo1988 的頭像
    melomelo1988

    melo 唐

    melomelo1988 發表在 痞客邦 留言(0) 人氣()