[英]hiding property from derived class
Jon Skeet在他的視頻中提到了這個問題(雖然沒有提供答案)。
假設我們有一個名為Person的類,而Person類具有Name屬性
然后我們有另一個班,間諜。 當然,間諜是一個人,所以我們將從Person類派生。
public class Person
{
public string Name { get; set; }
}
public class Spy : Person
{
}
我們不希望人們知道Spy的名字,所以我們希望這會給出一個編譯錯誤:
static void ReportSpy(Spy spy) {
string name = spy.Name;
}
或者:
static void ReportSpy(Spy spy)
{
Person spyAsPerson = spy;
string name = spyAsPerson.Name;
}
我們怎么能防止這種事情發生呢?
在基本Person
類Person
Name
屬性為virtual
。 在派生的Spy
類中,覆蓋該屬性並在getter中throw Exception
。
public class Person
{
public virtual string Name { get; set; }
}
public class Spy : Person
{
public override string Name
{
get
{
throw new Exception("You never ask for a spy's name!");
}
set
{
base.Name = value;
}
}
}
但是,我建議不要拋出異常
get
{
return "**********";
}
因為,它打破了LSP (在另一個答案中提到)。 這意味着什么(只是一個例子),我總是可以這樣做
Person x = new Spy();
並將其傳遞給其他方法,可能就像
void RegisterForNextBallGame(Person p)
{
playerList.Add(p.Name);
}
這種方法不知道體育場周圍的一些間諜漫游,在做一個簡單的誠實任務時崩潰!
編輯
為了說清楚,這個name=**********
仍然不是一個正確的解決方案 。 它只會從異常中拯救! 之后,人們可能會發現許多人在名稱為**********的代碼中走下來,這將導致后來的驚喜和其他問題。
更好的解決方案是更好的設計。 檢查內森的答案以獲得一些暗示。
如果作為一個人的一部分透露了你的名字:間諜不是人
讓間諜繼承人破壞了Liskov替換原則 :一個對象可以用它的子類型替換。
如果Spys沒有透露他們的名字,他們就不應該是您設計環境中的人物。 也許您可以設計不同的方式:
public interface IPerson
{
void EatLunch();
}
public interface INameDisclosingPerson : IPerson
{
string Name {get; set; }
}
public interface ISpy : IPerson
{
void DrinkCocktail();
Package MakeDrop();
}
現實世界中這種糟糕設計的一個例子是NetworkStream 。 它通過拋出NotSupportedException來實現Position
屬性。 因此,為Stream
編寫的代碼可能會在運行時為NetworkStream
中斷。 我也不是這個的粉絲。 一個設計指南:錯誤的東西應該在編譯時破壞,從它們無法實現的接口繼承的對象是可怕的。
您可以使用new
關鍵字隱藏基類方法或屬性:
public class Person
{
public string Name { get; set; }
}
public class Spy : Person
{
public new string Name
{
get { throw new InvalidOperationException(); }
}
}
它不會給你編譯錯誤,如果你強制轉換,你仍然可以訪問基類Name
屬性。
如果可以修改基類,請將屬性更改為虛擬。 然后你可以在derived和class中覆蓋它,並且即使使用多態調用也會拋出異常。
所有這些都將在運行時工作,在編譯時你無能為力。
正如其他人在答案中提到的那樣,這種設計打破了利斯科夫的替代原則,應該避免。
你不能。 如前所述,在訪問Spy的Name屬性時可能會拋出異常,但這仍然可以編譯。 並且,也已經提到過,這將打破Liskov替代原則,並且我想補充一點,即開放封閉原則。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.