我想知道,如果你想从原始基继承一个方法,而不是直接继承,是否可以跳过继承三中的一个类。
例如,假设我有三个类,GrandParent、Parent (从GrandParent继承)和Child (从Parent继承)。GrandParent有一个方法Adresse,而Parent有一个重写它的方法Adresse。但是,假设出于某种原因,我希望Child具有与GrandParent相同的Adresse方法,而不是Parent。如果我遇到这样的情况,有没有可能或者我搞砸了?
下面的示例代码是C#格式的
class GrandParent
{
private String Adresse;
public GrandParent()
{
}
public virtual void setAdress(String Adresse)
{
this.Adresse = Adresse;
}
public String getAdress()
{
return Adresse;
}
}
class Parent : GrandParent
{
public Parent()
:base()
{
}
public override void setAdress(String Adresse)
{
base.setAdress("Home: " + Adresse);
}
}
class Child : Parent
{
public Child()
: base()
{
}
}发布于 2016-12-25 01:47:59
如果你有这样的问题,那就意味着你的应用程序设计得很差。你需要学习可靠的设计原则。在这种情况下,Liskov substitution principle会很有用。使用继承时,请始终验证关系是否为IS-A。
理想情况下,代码重用应该通过组合而不是继承来完成。
如果你仍然想使用继承,我可以想出几种方法来解决这个问题。
第一种可能性是添加将被使用而不是Parent的NewChild类,特定的功能将在该类中,共享功能将保留在现有的Parent中。但是,您可能决定为新的子类保留现有名称,并为现有类找到另一个名称。
另一种不太干净的可能性是添加一些受保护的方法用于代码共享目的。
但我认为,如果你想保持原来的层次结构,修改Parent.setAddress方法,这样特殊的行为依赖于其他东西,比如传递给构造函数的布尔值,可能会更好。
本质上,继承应该遵循IS-A规则和其他方法应该用于代码重用。它可能是一些受保护的方法,用于潜在的公共部分,甚至其他类。
发布于 2016-12-27 00:01:09
没有一种clean方法可以“跳过继承树中的类”。如果你发现自己需要这样做(因为只有一个方法有这个混蛋的要求),我建议完全删除继承,在顶级类中使用只读委托来定义默认行为,并允许每个子类创建自己的委托,或者(如果它想要顶级行为而不是父类的)重置为顶级委托:
delegate string GetMyAddress(string baseAddress);
class Grandparent
{
protected readonly GetMyAddress _baseGetMyAddress;
protected GetMyAddress _getMyAddress;
public string BaseAddress = "Foo Street";
public Grandparent()
{
_baseGetMyAddress = (a) => { return String.Format("Grandparent: {0}", a); };
_getMyAddress = _baseGetMyAddress;
}
// no longer virtual
public string MyAddress()
{
return _getMyAddress(BaseAddress);
}
}
class Parent : Grandparent
{
public Parent()
{
// does something differing from the base
_getMyAddress = (a) => { return String.Format("Parent: {0}", a); };
}
}
class Child : Parent
{
public Child()
{
// does what its parent tells it to do
}
}
class ChildTakingAfterGrandparent : Parent
{
public ChildTakingAfterGrandparent()
{
// does what its grandparent does
_getMyAddress = _baseGetMyAddress;
}
}
class WillfulChild : Parent
{
public WillfulChild()
{
// does its own thing
_getMyAddress = (w) => { return String.Format("WillfulChild: {0}", w); };
}
}
public static void Run()
{
var gp = new Grandparent();
var p = new Parent();
var c = new Child();
var cg = new ChildTakingAfterGrandparent();
var wc = new WillfulChild();
Console.WriteLine("gp.MyAddress(): \"{0}\"", gp.MyAddress());
Console.WriteLine("p.MyAddress(): \"{0}\"", p.MyAddress());
Console.WriteLine("c.MyAddress(): \"{0}\"", c.MyAddress());
Console.WriteLine("cg.MyAddress(): \"{0}\"", cg.MyAddress());
}调用Run()方法将显示以下内容:
gp.MyAddress(): "Grandparent: Foo Street"
p.MyAddress(): "Parent: Foo Street"
c.MyAddress(): "Parent: Foo Street"
cg.MyAddress(): "Grandparent: Foo Street"
wc.MyAddress(): "WillfulChild: Foo Street"https://stackoverflow.com/questions/41314672
复制相似问题