C#: Any way to skip over one of the base calls in polymorphism?

后端 未结 7 1277
一个人的身影
一个人的身影 2021-01-17 16:34
class GrandParent
{
    public virtual void Foo() { ... }
}

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

       //Do additi         


        
相关标签:
7条回答
  • 2021-01-17 16:43

    No. It wouldn't be reliable anyway. You, as the implementer of your class, get to choose your immediate base class. But who is to say that a later release of Parent might not inherit from ParentBase, that in turn inherits from GrandParent? So long as Parent is still implementing the correct contract, this should not cause any issues for those classes inheriting from Parent.

    0 讨论(0)
  • 2021-01-17 16:43

    No, this isn't possible. Imagine how crazy things would be if this was possible.

    If you want something specific skipped in the Child case, consider reworking your design to better represent what you need (e.g. maybe you need to override something else in the Child class, too). Or, you could provide another Foo() in the Parent class that doesn't do anything except call its base.Foo().

    0 讨论(0)
  • 2021-01-17 16:47

    All these strong opinions...

    Sometimes it just makes sense to use 99% of something...

    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();
      }
    }
    
    0 讨论(0)
  • 2021-01-17 16:52

    Your design is wrong if you need this.
    Instead, put the per-class logic in DoFoo and don't call base.DoFoo when you don't need to.

    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)
        }
    }
    
    0 讨论(0)
  • 2021-01-17 17:00

    I think there is something wrong with your design here. Essentially, you want to "break" the rules of polymorphism. You are saying Child should derive from Parent but want to conveniently skip the implementation in it's parent.

    Re-think your design.

    0 讨论(0)
  • 2021-01-17 17:00

    We had exactly this scenario on a large project where the derived methods were called from various locations. Due to change management and QA scripts not to be broken, among other constraints, "drastic" refactoring and class re-structuring are not always possible on a large mature project. Also we did not want to override the method and exclude all base functionality. Most solutions seen elsewhere, looked a bit clumsy, but the solution from Josh Jordan on How to call base.base was quite useful.

    However we followed the approach below (which I see now is very similar to what Dan Abramov propose).

    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.
        }
    }   
    

    0 讨论(0)
提交回复
热议问题