【问题标题】:Inheritance, inherit from original base继承,从原始基础继承
【发布时间】:2016-12-24 15:46:09
【问题描述】:

我想知道如果你想从原始基类继承一个方法,而不是你的直接前任,是否可以跳过继承三中的一个类。

例如,假设我有三个类,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()
    {

    }
}

【问题讨论】:

  • 从语法来看,问题似乎是针对 C++ 的。你能确认和更新吗?这也将帮助其他试图回答您的问题的人。另请查看this 问题是否对您有帮助。
  • 这就是我在 Parent 中所做的:示例中的 base 。但是,如果我在 Child 中执行此操作,我仍然会在 Parent 中调用 Adresse 方法,因为 parent 是 Child 的直接基础
  • 看看这个答案(以及这个问题中的其他答案)是否有帮助:stackoverflow.com/a/32562464/5311735

标签: c# inheritance


【解决方案1】:

如果您遇到此类问题,则意味着您的应用程序设计不佳。您需要了解 SOLID 设计原则。在这种情况下,Liskov substitution principle 会很有用。使用继承时,请始终验证关系是否为 IS-A。

理想情况下,代码重用应该通过组合而不是继承来完成。

如果你仍然想使用继承,我可以想一些办法来解决这个问题。

第一种可能性是添加NewChild 类,而不是Parent,特定功能将在该类中,共享功能将保留在现有Parent 中。但是,您可能决定保留新孩子的现有名称,并为现有类找到另一个名称。

另一种不太干净的可能性是添加一些受保护的方法用于代码共享。

但我认为如果您想保留原始层次结构可能会更好,因为它可以修改 Parent.setAddress 方法,以便特殊行为依赖于其他东西,例如传递给构造函数的布尔值。

从本质上讲,继承应该遵循 IS-A 规则,并且应该使用其他方式进行代码重用。 对于潜在的公共部分甚至其他类,它可能是一些受保护的方法。

【讨论】:

    【解决方案2】:

    没有“跳过继承树中的类”的干净方法。如果您发现自己需要这样做(因为在众多方法中只有一种方法具有这种混蛋要求),我建议您完全删除继承,在顶级类中使用只读委托来定义默认行为,并允许每个子类要么创建自己的委托,要么(如果它想要顶级行为而不是其父行为)重置为顶级委托:

        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"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-21
      • 1970-01-01
      • 1970-01-01
      • 2014-12-26
      • 2016-11-13
      • 1970-01-01
      • 2011-03-03
      • 2011-04-24
      相关资源
      最近更新 更多