2013-12-18 38 views
1

什麼是真正的實際使用'new' modifier的?成員隱藏,什麼是它的實際用途

public class Base 
{ 
    public void Say() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

public class Derived:Base 
{ 
    public new void Say() 
    { 
     Console.WriteLine("Derived"); 
    } 
} 

如果這只是不能編譯,它會更好嗎?此代碼:

 Derived d = new Derived(); 
     d.Say(); 
     ((Base)d).Say(); 

返回

Derived 
Base 

這是否打破了里氏替換原則?

乾杯。

+2

法律可以被打破或彎曲時,他們滿足現實世界 - http://en.wikipedia.org/wiki/Circle-ellipse_problem – Kami

回答

2

關於LSP

這不破LSP。 的LSP指出,如果DerivedBase子類型,則根據Base任何碼(例如,具有Base參數的方法,像void DoSomething(Base b))可以與的Derived實例替換,而沒有任何令人驚訝的效果。

正如您所指出的那樣,如果您將Derived的實例分配給Base變量,則將調用Base實現。

這是預期的行爲,因爲Say不虛。這意味着書面反對Base變量的代碼,預計Base執行被調用。

實用目的

你能想到的new方法,以此來規避非重寫的方法 - 用一個警告!您必須針對該特定類型進行編程 - 而不是其接口。

1

雖然這不是一個好的做法,以做到這一點,我可以看到它是有用的,當你從一個第三方組件繼承(即代碼,你就不用管了),你希望有一個方法,不同的行爲。

+0

但你*不*覆蓋的方法之一,當你做這個。這是有點點。 – Servy

+0

我不是說覆蓋關鍵字,但有不同的行爲。我會更新答案... –

+1

我不是在談論關鍵字覆蓋,而是在概念。你回答同樣的問題,因爲你正在接受同樣的概念。如果該方法是虛擬的,並且您覆蓋它,那麼您確實正在有效地更改該方法的實現。從概念的角度來看,隱藏你只是創建一個全新的方法(因此使用'new'關鍵字),並明確地*不*改變現有的方法。它仍然存在,完全沒有改變。 – Servy

1

在派生類的方法被認爲是它的基類「相關」的方法,如果它具有相同的名稱和參數列表。編譯器設計人員處理此類相關的方法有兩種方法:

  1. 依靠慣例 - 例如,他們可以宣佈這種方法的重寫; Java這樣做。從程序員
  2. 請求明確方向 - C#設計了這條路線:他們要求程序員指定與virtual/override相關的方法,並與new無關的方法。

處理的第一種方式心花怒放方法葉程序員別無選擇:如果他們想要一個不相關的方法,他們必須給它一個不同的名稱。第二種方式是讓程序員離開選擇,代價是更加冗長。

從本質上講,new關鍵字可以讓您向編譯器傳達您添加的方法與基類中具有相同名稱和參數的方法無關。

這是否打破了里氏替換原則?

可以說,它沒有的事實:在派生類中已經推出了具有相同的名稱和參數,程序員明確指定爲無關基座中的方法的方法,在行爲並不能改變什麼在派生類用作其基類的替代品的情況下。

1

它簡單地允許用戶重新定義的基類的方法。當然,有預見這個偶然的開發者,你會希望他們不得不編碼它作爲虛擬(對於一個默認的實現)或抽象的(其中任何實現需要指定)。

的LSP簡單地把剛需要一個基類,子類可以互換使用,所以這不違反原則,據我可以看到。

的C#甲小缺點是,只有一個類可以繼承這樣的情況下,例如這應該是複雜的系統,其中所述多個執行的接口將是優選的比較少見。

1

DerivedBase和客戶端都在你的控制這可能是有用的。假設你從此開始。

 

public class Base 
{ 
    // there is no Say method in Base! 
} 

public class Derived:Base 
{ 
    public /*new*/ void Say() // we don't need new here 
    { 
     Console.WriteLine("Derived"); 
    } 
} 
 

然後有一天那些誰負責Base加入涼Say方法那裏。你可能已經改名爲Derived.Say,但它已經在你無法改變的代碼的其他地方使用過了。因此,您使用new以避免在Derived中發生重大更改。

 

public class Base 
{ 
    public void Say() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

public class Derived:Base 
{ 
    public new void Say() 
    { 
     Console.WriteLine("Derived"); 
    } 
} 

public class SomeClient 
{ 
    public void Run() 
    { 
     var d = new Derived(); 
     d.Say(); 
    } 
} 
 
相關問題