Multiple inheritance in C #: what is a purist way to achieve what I'm trying to do?

I understand that there is no multiple inheritance in C #. However, I came across a situation in which I really wanted it to exist. I am creating a custom class that requires me to inherit from CLR types and override several methods. Unfortunately, I create several of them that are very similar. In the interests of DRY, I would really like to translate the general functionality into a base class, but then I would need to inherit 2 classes. I can use interfaces (and infact I'm using one right now), but this only solves half the problem, since the implementation of the method should still be repeated in several user classes.

What a purist way to achieve what I'm trying to do?

EDIT:

Here is an example of typical code

public class CustomTypeOne : CLRType
{
   public override void Execute(HttpContext context)
   {
        //Some code that similar across CustomTypeOne, CustomTypeTwo etc
   }

   public void DoStuff()
   {
       //Same for all CustomTypes and can be part of a base class
   }

   //More methods
}

public class CustomTypeTwo : CLRType
{
   public override void Execute(HttpContext context)
   {
        //Some code that similar across CustomTypeOne, CustomTypeTwo etc
   }

   public void DoStuff()
   {
       //Same for all CustomTypes and can be part of a base class
   }

   //More methods

}
+5
source share
9 answers

There are several ways to implement what you are talking about.

Assuming you have a structure like

MyTypeA : CLR_TypeA
{
    public override ToString()
    {
       //do some complicated stuff
    }
}
MyTypeB : CLR_TypeB
{
    public override ToString()
    {
       //do the same complicated stuff
    }
}

Then it makes sense to want to have a base class, but you cannot. One of the methods that is mentioned in other answers is composition. However, in your case it is possible to create another static class

public static class ToStringHelpers
{
    public static DoComplicatedStuff()
    {
       //do some pretty wild stuff.
    }
}

MyTypeA : CLR_TypeA
{
    public override ToString()
    {
       DoComplicatedStuff();
    }
}
MyTypeB : CLR_TypeB
{
    public override ToString()
    {
       DoComplicatedStuff();
    }
}

, , . , "DoComplicatedStuff()" , / .

, MI

MyBaseType : CLRType
{
   public override void Execute(HttpContext context)
   {
       //Some code that similar across CustomTypeOne, CustomTypeTwo etc
   }

   public void DoStuff()
   {
      //Same for all CustomTypes and can be part of a base class
   }

}

MyTypeA : MyBaseType
{
    public void MyTypeACustomMethod()
    { 
      //do class specific logic here
    }
}

MyTypeB : MyBaseType
{
    public void MyTypeBCustomMethod()
    { 
      //do class specific logic here
    }
}
+2

, , , , . MI , , .

, IS-A, HAS-A. , , .

+10

, .

, .

+2

, CLR, .

class BaseClass<T> where T : struct
{
   public override void Execute(HttpContext context) 
   { 
        //Some code that similar across CustomTypeOne, CustomTypeTwo etc 
   } 

   public void DoStuff() 
   { 
       //Same for all CustomTypes and can be part of a base class 
   } 

}

public class CustomTypeOne : BaseClass<int>
{
}

public class CustomTypeTwo : BaseClass<long>
{
}

( , , CLR....)

+1

- , .

+1

, . , , , , , . ( ), .

public abstract class BaseClass { }

public interface IMyClass { }

internal interface IMyClassImpl { }

public class MyClass : BaseClass, IMyClass, IMyClassImpl
{
    //IMyClassImpl members should be implemented explicitly, so they are inaccessible to outside clients.
}

public static class MyClassExtensions
{
    public static void HelperMethod(this IMyClass instance)
    {
        //Do stuff...
        //Can access internal implementation as necessary
        var impl = (IMyClassImpl)instance;
        impl.InternalHelperMethod();
    }

    internal static void InternalHelperMethod(this IMyClassImpl instance)
    {

    }
}

, , , , , , .

+1

, . , , - , .

, , , . , (, MVVM), . , .

+1

Composition is the preferred alternative to inheritance. There are always exceptions and special cases, but if you can solve the composition problem, you will most likely get more flexible code than if you were using inheritance.

0
source

You can create a new object that contains common functionality and use the composition of the object instead of inheritance.

For example, use depency injection to inject your object, which contains common functionality, into your objects.

0
source

All Articles