Multiple Inheritance in C#

后端 未结 15 1971
醉酒成梦
醉酒成梦 2020-11-22 03:03

Since multiple inheritance is bad (it makes the source more complicated) C# does not provide such a pattern directly. But sometimes it would be helpful to have this ability.

15条回答
  •  耶瑟儿~
    2020-11-22 03:19

    Since the question of multiple inheritance (MI) pops up from time to time, I'd like to add an approach which addresses some problems with the composition pattern.

    I build upon the IFirst, ISecond,First, Second, FirstAndSecond approach, as it was presented in the question. I reduce sample code to IFirst, since the pattern stays the same regardless of the number of interfaces / MI base classes.

    Lets assume, that with MI First and Second would both derive from the same base class BaseClass, using only public interface elements from BaseClass

    This can be expressed, by adding a container reference to BaseClass in the First and Second implementation:

    class First : IFirst {
      private BaseClass ContainerInstance;
      First(BaseClass container) { ContainerInstance = container; }
      public void FirstMethod() { Console.WriteLine("First"); ContainerInstance.DoStuff(); } 
    }
    ...
    

    Things become more complicated, when protected interface elements from BaseClass are referenced or when First and Second would be abstract classes in MI, requiring their subclasses to implement some abstract parts.

    class BaseClass {
      protected void DoStuff();
    }
    
    abstract class First : IFirst {
      public void FirstMethod() { DoStuff(); DoSubClassStuff(); }
      protected abstract void DoStuff(); // base class reference in MI
      protected abstract void DoSubClassStuff(); // sub class responsibility
    }
    

    C# allows nested classes to access protected/private elements of their containing classes, so this can be used to link the abstract bits from the First implementation.

    class FirstAndSecond : BaseClass, IFirst, ISecond {
      // link interface
      private class PartFirst : First {
        private FirstAndSecond ContainerInstance;
        public PartFirst(FirstAndSecond container) {
          ContainerInstance = container;
        }
        // forwarded references to emulate access as it would be with MI
        protected override void DoStuff() { ContainerInstance.DoStuff(); }
        protected override void DoSubClassStuff() { ContainerInstance.DoSubClassStuff(); }
      }
      private IFirst partFirstInstance; // composition object
      public FirstMethod() { partFirstInstance.FirstMethod(); } // forwarded implementation
      public FirstAndSecond() {
        partFirstInstance = new PartFirst(this); // composition in constructor
      }
      // same stuff for Second
      //...
      // implementation of DoSubClassStuff
      private void DoSubClassStuff() { Console.WriteLine("Private method accessed"); }
    }
    

    There is quite some boilerplate involved, but if the actual implementation of FirstMethod and SecondMethod are sufficiently complex and the amount of accessed private/protected methods is moderate, then this pattern may help to overcome lacking multiple inheritance.

提交回复
热议问题