【问题标题】:C#: Any way to skip over one of the base calls in polymorphism?C#:有什么方法可以跳过多态性中的一个基本调用?
【发布时间】:2011-08-02 14:19:17
【问题描述】:
class GrandParent
{
    public virtual void Foo() { ... }
}

class Parent : GrandParent
{
    public override void Foo()
    {
       base.Foo();

       //Do additional work
    }
}

class Child : Parent
{
    public override void Foo()
    {
        //How to skip Parent.Foo and just get to the GrandParent.Foo base?

        //Do additional work
    }
}

如上面的代码所示,我怎样才能让 Child.Foo() 调用 GrandParent.Foo() 而不是进入 Parent.Foo()? base.Foo() 先带我去 Parent 课。

【问题讨论】:

  • 我很确定 .net 运行时支持这一点。相关阅读blogs.msdn.com/b/ericlippert/archive/2010/03/29/…
  • 也许如果你说明为什么你想这样做,我们可以帮助你重新设计你的架构?
  • @CodeInChaos:即使支持也会导致ChaosInCode。

标签: c# inheritance polymorphism overriding virtual-functions


【解决方案1】:

如果你需要这个,你的设计是错误的。
相反,将每个类的逻辑放在DoFoo 中,并且不要在不需要时调用base.DoFoo

class GrandParent
{
    public void Foo()
    {
        // base logic that should always run here:
        // ...

        this.DoFoo(); // call derived logic
    }

    protected virtual void DoFoo() { }
}

class Parent : GrandParent
{
    protected override void DoFoo()
    {    
       // Do additional work (no need to call base.DoFoo)
    }
}

class Child : Parent
{
    protected override void DoFoo()
    {  
        // Do additional work (no need to call base.DoFoo)
    }
}

【讨论】:

  • 你需要使 GrandParent abstract 才能工作。完成这个告诉你'GrandParent.DoFoo()' is abstract but it is contained in non-abstract class 'GrandParent'
【解决方案2】:

我认为你的设计有问题。本质上,您想“打破”多态性规则。您是说 Child 应该派生自 Parent 但想方便地跳过其父级中的实现。

重新思考您的设计。

【讨论】:

    【解决方案3】:

    没有。反正也不靠谱。你,作为你的类的实现者,可以选择你的直接基类。但谁能说Parent 的更高版本可能不会继承自ParentBase,而后者又继承自GrandParent?只要Parent 仍在实现正确的契约,这不会对那些继承自Parent 的类造成任何问题。

    【讨论】:

      【解决方案4】:

      不,这是不可能的。想象一下,如果这是可能的事情会是多么疯狂。

      如果您希望在 Child 案例中跳过某些特定内容,请考虑重新设计您的设计以更好地表达您的需求(例如,您可能还需要覆盖 Child 类中的其他内容)。或者,您可以在 Parent 类中提供另一个 Foo(),除了调用它的 base.Foo() 之外什么都不做。

      【讨论】:

        【解决方案5】:

        如果您可以控制代码,最简单的方法是在 Parent 类中创建一个仅调用 base.Foo() 的受保护方法,并且您的子类 Foo 实现显式调用该方法

        【讨论】:

          【解决方案6】:

          我们在一个大型项目中恰好遇到了这种情况,其中派生方法从不同位置调用。由于变更管理和 QA 脚本不能被破坏,除其他限制外,在大型成熟项目中并不总是可以进行“剧烈”重构和类重组。此外,我们不想覆盖该方法并排除所有基本功能。在其他地方看到的大多数解决方案看起来有点笨拙,但来自Josh Jordan on How to call base.base 的解决方案非常有用。

          但是我们采用了以下方法(我现在看到的方法与 Dan Abramov 提出的方法非常相似)。

          
          
          
          public class Base
          {
              public virtual void Foo()
              {
                  Console.WriteLine("Hello from Base");
              }
          }
          
          public class Derived : Base
          {
              public override void Foo()
              {
                  base.Foo();
                  Console.WriteLine("Text 1");
                  WriteText2Func();
                  Console.WriteLine("Text 3");
              }
          
              protected virtual void WriteText2Func()
              {
                  Console.WriteLine("Text 2");
              }
          }
          
          public class Special : Derived
          {
              public override void WriteText2Func()
              {
                  //WriteText2Func will write nothing when method Foo is called from class Special.
                  //Also it can be modified to do something else.
              }
          }   
          

          【讨论】:

            【解决方案7】:

            所有这些强烈的意见......

            有时使用 99% 的东西才有意义...

            public class Base
            {
              public virtual void Foo()
              {
               // Do something
              }
            }
            
            public class DerivedLevel1 : Base
            {
              public override void Foo()
              {
                DerivedLevel1Foo();
              }
              protected void DerivedLevel1Foo()
              {
                // Do something
                base.Foo();
              }
            }
            
            public class DerivedLevel2 : DerivedLevel1
            {
              public override void Foo()
              {
               DerivedLevel2Foo();
              }
              protected void DerviedLevel2Foo()
              {
                // Do something
                base.Foo();
              }
            }
            
            public class Special : Derived
            {
              public override void Foo()
              {
                // Don't do DerivedLevel2Foo()
                base.DerivedLevel1Foo();
              }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-07-12
              • 2023-04-02
              • 1970-01-01
              • 1970-01-01
              • 2011-02-20
              • 1970-01-01
              • 1970-01-01
              • 2012-06-29
              相关资源
              最近更新 更多