Multiple Inheritance in C#

后端 未结 15 1824
醉酒成梦
醉酒成梦 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.

    0 讨论(0)
  • 2020-11-22 03:20

    MI is NOT bad, everybody that has (seriously) used it LOVES it and it doesNOT complicate the code! At least not anymore than other constructs may complicate the code. Bad code is bad code regardless of whether or not MI is in the picture.

    Anyway, I've got a nice little solution for Multiple Inheritance I wanted to share, it's at; http://ra-ajax.org/lsp-liskov-substitution-principle-to-be-or-not-to-be.blog or you can follow the link in my sig... :)

    0 讨论(0)
  • 2020-11-22 03:20

    If X inherits from Y, that has two somewhat orthogonal effects:

    1. Y will provide default functionality for X, so the code for X only has to include stuff which is different from Y.
    2. Almost anyplace a Y would be expected, an X may be used instead.

    Although inheritance provides for both features, it is not hard to imagine circumstances where either could be of use without the other. No .net language I know of has a direct way of implementing the first without the second, though one could obtain such functionality by defining a base class which is never used directly, and having one or more classes that inherit directly from it without adding anything new (such classes could share all their code, but would not be substitutable for each other). Any CLR-compliant language, however, will allow the use of interfaces which provide the second feature of interfaces (substitutability) without the first (member reuse).

    0 讨论(0)
  • 2020-11-22 03:26

    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.

    C# and the .net CLR have not implemented MI because they have not concluded how it would inter-operate between C#, VB.net and the other languages yet, not because "it would make source more complex"

    MI is a useful concept, the un-answered questions are ones like:- "What do you do when you have multiple common base classes in the different superclasses?

    Perl is the only language I've ever worked with where MI works and works well. .Net may well introduce it one day but not yet, the CLR does already support MI but as I've said, there are no language constructs for it beyond that yet.

    Until then you are stuck with Proxy objects and multiple Interfaces instead :(

    0 讨论(0)
  • 2020-11-22 03:29

    Multiple inheritance is one of those things that generally causes more problems than it solves. In C++ it fits the pattern of giving you enough rope to hang yourself, but Java and C# have chosen to go the safer route of not giving you the option. The biggest problem is what to do if you inherit multiple classes that have a method with the same signature that the inheritee doesn't implement. Which class's method should it choose? Or should that not compile? There is generally another way to implement most things that doesn't rely on multiple inheritance.

    0 讨论(0)
  • 2020-11-22 03:30

    We all seem to be heading down the interface path with this, but the obvious other possibility, here, is to do what OOP is supposed to do, and build up your inheritance tree... (isn't this what class design is all about?)

    class Program
    {
        static void Main(string[] args)
        {
            human me = new human();
            me.legs = 2;
            me.lfType = "Human";
            me.name = "Paul";
            Console.WriteLine(me.name);
        }
    }
    
    public abstract class lifeform
    {
        public string lfType { get; set; }
    }
    
    public abstract class mammal : lifeform 
    {
        public int legs { get; set; }
    }
    
    public class human : mammal
    {
        public string name { get; set; }
    }
    

    This structure provides reusable blocks of code and, surely, is how OOP code should be written?

    If this particular approach doesn't quite fit the bill the we simply create new classes based on the required objects...

    class Program
    {
        static void Main(string[] args)
        {
            fish shark = new fish();
            shark.size = "large";
            shark.lfType = "Fish";
            shark.name = "Jaws";
            Console.WriteLine(shark.name);
            human me = new human();
            me.legs = 2;
            me.lfType = "Human";
            me.name = "Paul";
            Console.WriteLine(me.name);
        }
    }
    
    public abstract class lifeform
    {
        public string lfType { get; set; }
    }
    
    public abstract class mammal : lifeform 
    {
        public int legs { get; set; }
    }
    
    public class human : mammal
    {
        public string name { get; set; }
    }
    
    public class aquatic : lifeform
    {
        public string size { get; set; }
    }
    
    public class fish : aquatic
    {
        public string name { get; set; }
    }
    
    0 讨论(0)
提交回复
热议问题