我们假设我们有一个名为Person的类 Person类具有Name属性
然后我们有另一个班,间谍。 当然Spy是一个Person,所以我们将派生于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;
}
我们怎么能防止这种事情发生?
答案 0 :(得分:6)
在基础Name
课程中设置virtual
属性Person
。在派生的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=**********
仍然不是一个正确的解决方案。它只会从异常中拯救!之后,人们可能会发现许多人在名称为**********的代码中走下来,这将导致后来的惊喜和其他问题。
更好的解决方案是更好的设计。检查内森的答案以获得一些暗示。
答案 1 :(得分:6)
如果一个人的一部分透露了你的名字:间谍不是人
让间谍继承人来打破Liskov substitution principle:对象可能会被其子类型替换。
如果Spys没有透露他们的名字,他们就不应该是您设计环境中的人物。也许你可以用不同的方式设计它:
char[]
现实世界中这种糟糕设计的一个例子是NetworkStream。它通过抛出NotSupportedException来实现unsigned char my_code[5] = {124,231,75,123,0};
asm("jal my_code");
属性。因此,为public interface IPerson
{
void EatLunch();
}
public interface INameDisclosingPerson : IPerson
{
string Name {get; set; }
}
public interface ISpy : IPerson
{
void DrinkCocktail();
Package MakeDrop();
}
编写的代码可能会在运行时因Position
而中断。我也不是这个的粉丝。一个设计指南:错误的东西应该在编译时破坏,从继承他们无法实现的接口的对象是可怕的。
答案 2 :(得分:1)
您可以使用new
关键字隐藏基类方法或属性:
public class Person
{
public string Name { get; set; }
}
public class Spy : Person
{
public new string Name
{
get { throw new InvalidOperationException(); }
}
}
它不会给你编译错误,如果你强制转换,你仍然可以访问基类Name
属性。
如果可以修改基类,请将属性更改为虚拟。然后你可以在derived和class中覆盖它,并且即使使用多态调用也会抛出异常。
所有这些都可以在运行时运行,在编译时你无能为力。
正如其他人在答案中提到的那样,这种设计打破了利斯科夫的替代原则,应该避免。
答案 3 :(得分:1)
你做不到。如前所述,在访问Spy的Name属性时可能会抛出异常,但这仍然可以编译。并且,也已经提到过,这将打破Liskov替换原则,并且我想补充一点,即开放封闭原则。