![]() |
||
Major Member
![]() 加入日期: Sep 2003
文章: 263
|
C#問題-多型 , 煩請高手大大解惑了~~
高手大大們好~
小弟最近在研究C# 的多型, 有些寫法在網路跟書上常看到,但是就是不曉得這 樣寫是什麼意思, 又不想自己隨便亂猜測,所以請高手大大指點, 以下是範例: 有一基底類別 CarClass class CarClass { public virtual void Run() { Console.WriteLine("Car is running"); } public virtual string GetName() { return "Car"; } } 以及一個衍生類別BenzClass class BenzClass:CarClass { public override void Run() { Console.WriteLine("Benz is running!"); } public new string GetName(); { return "Benz"; } } 客戶端的程式碼是: static void Main(string[] args) { BenzClass Benz = new BenzClass(); CarClass Base = (CarClass)Benz; Console.WriteLine(Benz.GetName()); Console.WriteLine(Base.GetName()); Console.ReadKey(); } 問題在客戶端程式碼這一行~ CarClass Base = (CarClass)Benz; 這是指物件Base 是將Benz 物件轉換成CarClass型別得到的嗎? 所以Base現在是屬於CarClass的實作物件囉? 如果是這樣, 為什麼不寫成 CarClass Base=new CarClass() 就好? 或者根本不是這樣? 上網路找多型資料, 結果好像大家對多型解釋不一, 有的跟繼承一點關係都沒有 . 就單純函式引數個數型別不同也有人稱為多型~~ 煩請高手大大解惑了~
__________________
時機歹歹 隨人顧性命 |
|||||||
![]() |
![]() |
*停權中*
加入日期: Mar 2014
文章: 49
|
就我對你問題的理解, 下面你參考 看看, 無針對語言性質.
多型其中一個用途, 當我寫好一個 methodA(BENZ) , 我可能目前只有 BENZ, 但以後有 LAMB 時, 這methodA 就不能用, 但如果是 methodA(CARClass), CARClass defined method startUrEngine() , 並實做了大眾規格的啟動方式 , methodA 內部實做會呼叫 CARClass.startUrEngine, BENZ 和 LAMB 繼承 CARClass , 假如這兩台車啟動行為不同, BENZ 和 LAMB 就會 override startUrEngine , 實做自己所需要的內容, 如果 LAMB 是用 大眾規格啟動方式, 就無需實作自己的啟動行為 , 但BENZ 啟動方式特殊, 所以他就override startUrEngine 實做自己的行為. 如此 methodA 不用因為今天多了 TOYOTA 這輛車就要改寫,只要他也繼承 CARClass 並override startUrEngine 實作了自己的行為. 這是多型的其中一種用法也有用 interface 來達到相同目的, 方法很多很難一一解釋, 端看你的需求而變化, 這邊只能說明概念, 希望有所幫助. 此文章於 2015-03-05 12:12 PM 被 T磨人v2 編輯. |
||
![]() |
![]() |
Major Member
![]() 加入日期: Sep 2003
文章: 263
|
引用:
感謝大大的指教~ 不過大大你好像只是在解釋virtual 與 override 的概念 當基底類別方法有可能被衍生類別覆蓋, 就要使用override 或 new 我想這是許多物件導向語言共同的特性 我這邊的問題是 CarClass 與 BenzClass 是不同類別, 擁有自己的method 雖然BenzClass是CarClass的衍生類別 CarClass Base = (CarClass)Benz; Base 是CarClass 的實作物件嗎? 或是只是由Benz物件轉型而來? 這樣寫法是有什麼含義嗎?
__________________
時機歹歹 隨人顧性命 |
|
![]() |
![]() |
*停權中*
加入日期: Mar 2014
文章: 49
|
BENZ 是繼承自 CarClass 理所當然可以轉型 CarClass
, 就你的code 他這樣轉不過是要呼叫 CarClass 所實作的 getName(), 這樣有什麼問題嗎? 還是我理解錯誤 ==??? |
![]() |
![]() |
Advance Member
![]() ![]() 加入日期: Jun 2003 您的住址: Taipei
文章: 442
|
你的程式輸出是什麼?是否2行都是"Benz"?我不確定C#的method定義裡的"virtual","new"和"override"的意義,所以不確定.
就你的問題回答: "CarClass Base = (CarClass)Benz; Base 是CarClass 的實作物件嗎? 或是只是由Benz物件轉型而來? 這樣寫法是有什麼含義嗎?" BenzClass繼承自CarClass,所以BenzClass的instance就是CarClass的instance.轉型只是我們想把Base這個物件當成CarClass的instance來操作. 這個例子裡只有一個super class和一個sub class,如果你多增加幾個sub class(BmwClass, AudiClass等等),然後生一個CarClass的容器(List, Set,或Array),任意丟一些上述sub class的instance進去,然後一個一個呼叫它們的run()或是getName()... 你有沒有發現到,你不需要知道這些容器裡的instance實際上是什麼型別(是Benz或BMW或Audi...),但它們都會"run",你呼叫它們的"getName()"都會回傳自己的名字.這就是一種"多型"的手法,你使用super class的界面(CarClass)操作sub class的實例,而不需要去cast它們,就可以得到sub class自己定義的行為.你可以運用這種手法,在程式中只使用super class,這樣往後你塞什麼sub class的instance,你的程式都不需要再大改了,這就是OOP的達到"元件重用"的方法之一.
__________________
現今世道,自爆文當故事書,站長的話做成語錄,幾百年前的文章嘛沒事就挖出來考古... ![]() 此文章於 2015-03-05 01:43 PM 被 harrisonlin 編輯. |
![]() |
![]() |
*停權中*
加入日期: Mar 2014
文章: 49
|
喔喔~~ 高手出現 說明果然 很清晰明瞭...... 給個 ∼讚∼
|
![]() |
![]() |
Major Member
![]() 加入日期: Sep 2003
文章: 263
|
引用:
喔喔~! 原來這就是轉型, 小弟買的書跟手上資料都沒有講到這一塊, 所以看到這種寫法, 熊熊給他不知道什麼意思~感謝大大, 現在有方向 可以去找資料了!!
__________________
時機歹歹 隨人顧性命 |
|
![]() |
![]() |
Major Member
![]() 加入日期: Sep 2003
文章: 263
|
引用:
是的, 兩行輸出都是Benz 大大你應該是相當資深的programmer 這種解釋內容我第一次看到, 跟網路上一堆八股說法截然不同 小弟一定會仔細研究~感謝兩位大大的幫忙, 讓小弟可以有方向可以繼續下去~!!
__________________
時機歹歹 隨人顧性命 |
|
![]() |
![]() |
Elite Member
加入日期: May 2002 您的住址: 地球的上面..
文章: 5,854
|
![]() virtual修飾詞在父類別(第一次)的的設計上..
會要求對宣告virtual修飾詞的方法進行實作... 這個修飾詞有時會很有用, 對於某些C#設計者來說, 它幾乎非常實用.... override一般要求對父類別的抽象化實作(某些中文教科書(或譯本)對其行為稱作具象化..)... 因此搭配abstract進行覆寫... 在很多教科書說明, 對其抽象化類別實作該抽象方法, 這表示對於具象化類別來說.. 這是一個方法簽名(簽章), 這是原文signature直接翻過去... virtual我是沒有特別常用拉, 大多都是override去覆寫父類別(實作抽象).. 父類別與子類別是IS關係... 按照某些教科書的說法... 1. 符合LSP原則 2. 抽象化(abstract/interface) 3. 盡可能職責單一或最少, 這很重要.. 否則日後有時維護會賭爛...因為繼承就意味著偶合關係的增強.. 4. 繼承超過三層以上的情況, 可能需要考慮重新設計或著在重新包裝(組合關係; HAVE/HAS)另外在 "注入". 除非你有把握日後腦袋還很靈光. 5. 當採用組合關係上去切割職責, 必須考慮其他原則, 例如LoD, 甚麼DIP等沙洨的. ![]() 此文章於 2015-03-05 02:44 PM 被 vxr 編輯. |
![]() |
![]() |
*停權中*
加入日期: Mar 2014
文章: 49
|
補充一下我上一篇, 剛剛老闆飄過, 沒時間打玩,
你如果要呼叫父類別的方法 只能再子類別 override 的方法中 用 base.方法去呼叫. |
![]() |
![]() |