<p$1$2$3$4$5$6>
c#有個new函數的文法,但是我覺得這個東西用途很少。很多時候容易出現設計上的錯誤。
<p$1$2$3$4$5$6>
基類有個虛A()函數,子類不想覆蓋,但是又想要這個名字,怎麼辦,那就是new A(){...}。
然後調用的時候,要想調用基類的,就用((基類)子類).A();要想用子類的,就子類.A();
<p$1$2$3$4$5$6>
為什麼說這個比較容易出現設計上的問題。
1.類繼承系統的“介面”只能擴大,不能縮小
比如,你基類有個A函數,有個B函數,子類可以增加個C函數,但是不應該只是提供A函數,而沒有B函數。這個不單是從文法上,還要從語義上能說得過去,這種通過多態調用和直接調用出現語義上差別的做法,必然隱藏很多出錯的因素在裡面。就好象成龍說的:你們看到是這樣,用了也應該是這樣的。
2.縮小都原因都是因為子類不是基類
我們知道設計繼承關係有個很直觀的法則:子類是基類。比如秋刀魚是魚。在設計過程中,如果出現要縮小,只能說一開始這個抽象依據就是錯誤的,比如鯨魚不是魚(如果魚定義了鯨魚所沒有的介面)。
既然放棄了這個法則,那就屬於濫用文法的範疇,而不屬於物件導向的範疇。嚴格來說,就是簡陋笨拙的複製粘貼行為。不是說不能用,只是沒有設計上的優勢罷了。
<p$1$2$3$4$5$6>
如果非要用,怎麼從設計上理解?
我的理解,這種在設計上的意義就是所謂的“實現繼承”。也就是子類只是為了利用基類的實現為目的。但是這種方式,也許對於c#來說,用組合比用繼承要好得多,為什嗎?因為c++ 有private繼承,但是c#沒有。
c++的私人繼承,子類不能通過基類來調用,這樣就根絕了多態調用的念頭。
<p$1$2$3$4$5$6>
----------------------------------------------------
想不到大家討論的那麼積極,下面對討論做一些摘要(更新到80樓):
Zhenway:可以用new來改寫同名返回函數的類型,比如把傳回型別由基類改為子類類型,這在很多情境是有用的。
卡通一下:new未必和函數有關,也可以用在欄位上,所以並不是只是針對多態的情境。(而原文只是討論了多態的情境)
林靜止水:
我通常在以下情況下使用new
1.不能對虛方法是用new
2.對屬性可使用new,並且是組合關係
3.比如某類a的屬性是類b,類c繼承類a,屬性需要繼承類b,新屬性可以用new
新屬性只完成強制轉換
淩晨的太陽:
記得VS的提示是這樣的,當你企圖用override來重寫一個函數,或者直接編寫一個函數的時候,如果該函數在基類中已被定義,並且沒有virtual的時候,會提示使用new關鍵字。屬性也可以使用new,情況差不多。
顯然,new的使用和LZ的情境完全不同,概念也完全不同。