Re: 虛擬函式的使用

看板C_Sharp作者 (いまがその時だ)時間15年前 (2009/02/18 01:48), 編輯推噓3(301)
留言4則, 4人參與, 最新討論串2/2 (看更多)
※ 引述《atowng (阿棠)》之銘言: : 書看了一陣子,還是不是很清楚這個東西該怎麼使用,我們說 : public class 父類別 : { : public virtual int 屬性名稱 : { : get{return 0;} : } : public virtual string 方法名稱(); : } : public class 子類別 : 父類別 : { : public new int 屬性名稱 : { : get{return 1;} : } : public overrde string 方法名稱(); : } : 一個是用"new"去取代原先父類別的成員,一個是使用"overrde"去覆寫父類別中的 : 虛擬成員。 : 這邊小弟就迷惑了:1.一個類別中可能有許多的成員,一個子類別去繼承了它,對於 : 父類別中的虛擬成員,子類別一定要覆寫嗎? : 2.我們知道C#中還有抽象類別與介面,也是可以實現物件的多型,這三者之間該怎麼 : 運用適當。 Abstract class 主要用來表達有同樣的 property / method / event 的物件 並且這些物件間會有繼承的關係,EX: +--正方形(Square) +----四邊形---+--長方形(Rectangle) | (Quadrangle) 形狀(Shape)----+----三角形-------+--等腰三角形(IsoscelesTriangle) | (Triangle) |--正三角形(RegularTraiangle) +----圓形 (Circle) 上面所有的有關形狀的 class 都由形狀這個 base abstract class 繼承而來 假設形狀這個 base class 有一個叫「算面積(CalcArea)」的 virtual function 這個「算面積()」的功能在形狀這個 class 裡絕對算不出來(因為沒長寬,也沒半徑) 但是你知道所有的形狀都可以算的出面積 於是你必需在所有繼承形狀的 class 裡實作這個「算面積()」 但是對於程式設計師來說,不管是什麼樣的形狀,只要繼承自形狀 都可以操作「形狀.算面積()」這個 base class 裡的 function 來求出它的面積 範例 code: Shape a = new Rectangle(width, height); Shape b = new RegularTriangle(base, height); double aa = a.CalcArea(); double ba = b.CalcArea(); 請注意上面 new 出來的物件是一個 Rectangle,一個 RegularTriagnle 但是都使用 Shape 這個 base class 做操作 再來談 interface,interface 和 abstract class 不同之處 在於它只是一種標記,只要有這種標記的 class,它就「必需」要「能執行」 該 interface 裡所宣告的所有的事項(包括 method, property, event) 也因此 interface 主要用來定立一些共通的操作界面 EX: 汽車喇叭可以按(Push)、販賣機的按鈕也可以按 但顯然我們不會用同一個 base class 來描述汽車喇叭和販賣機 另外一般來說,interface 給人的感覺會很像簡易版的抽像類別 但它有以下的不同點 1、interface 裡所有被宣告的 property、method、event 都是 public 的 abstract class 裡你可以有 private 和 protected 的相關宣告 2、interface 裡所有被宣告的 property、method 都必需要被繼承且實作才能使用 abstract class 你可以不用實作,因為你可以 new 一個 abstract class 雖然那沒什麼意義,但是你沒辦法直接 new 一個 interface 你必需 new 出繼承了該 interface 並實作的 class, 再從那上面取得(Query)該interface 3、interface 在 C# 裡可以多重繼承,class 只能單一繼承 上面看了一定霧殺殺,我用剛剛的 shape 來舉例子 像上面所有繼承自 Shape 的 class 都可以算面積 也因此我可以宣告一個 interface 叫 ICanCalcArea 裡面有一個 CalcArea(),代表含有這個 interface 的 class 都要可以執行 CalcArea() 這件工作 interface ICanCalcArea { double CalcArea(); } 也因此 public class Triangle() : ICanCalcArea { ..... } public class Rectangle() : ICanCalcArea { ..... } 這代三角形和長方形的 class 都可以含有 ICanCalcArea 這個 interface 也就是說它們都可以算面積,那這樣和 abstract class 有什麼不一樣嗎? 我們再加上一個 class public class Robot() : ICanCalcArea, IRobotAction { ..... } 一個和形狀扯不上邊的 class -> Robot(機器人) 也可以含有這個 interface 只要它被宣告含有這個 interface,管你是機器人還是火箭,它就是要能夠算面積 並且上面的宣告中,Robot這個 class 還含有另一個 IRobotAction 的 interface 這代表 Robot 這個 class 也必需要能執行 IRobotAction 裡宣告的工作 而 interface 的使用呼叫上也是有所不同的: // new 出一個 Rectangle 物件 a Rectangle a = new Rectangle(Width, Height); // 從 a 上 query 出 ia 這個 ICanCalcArea 的 interface ICanCalcArea ia = a as ICanCalcArea; // 使用 query 出的 ICanCalcArea 的 interface 來執行 CalcArea() if (ia != null) double aa = ia.CalcArea(); 那 Robot 呢? Robot b = new Robot(....); ICanCalcArea ib = b as ICanCalcArea; if (ib != null) double ba = ib.CalcArea(); // 接下來 Query 出 IRobotAction 來執行這個 interface 上的工作 IRobotAction irab = b as IRobotAction; if (irab != null) irab.自爆(); //執行 IRobotAction 裡的 method 自爆 先寫到這,有錯請幫忙訂正 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 122.116.82.44 ※ 編輯: toki 來自: 122.116.82.44 (02/18 01:50)

02/18 16:44, , 1F
真是…非常詳盡…
02/18 16:44, 1F

02/18 18:03, , 2F
不推怎麼行ㄋ...
02/18 18:03, 2F

02/19 16:41, , 3F
感謝分享~受教了!
02/19 16:41, 3F

02/20 23:55, , 4F
講解得非常清楚,推薦!
02/20 23:55, 4F
文章代碼(AID): #19clXJZ7 (C_Sharp)
討論串 (同標題文章)
文章代碼(AID): #19clXJZ7 (C_Sharp)