Introduction
Whilst a class in C# can implement multiple interfaces, it can only inherit from a single class.
This is known as a 'single inheritance model' and is the model used by other popular object-oriented languages such as Java and Delphi.
However, some object-oriented languages such as C++ and Eiffel support a 'multiple inheritance model' where a class can inherit from several other classes. Although this model suffers from the 'diamond problem' (see http://en.wikipedia.org/wiki/Diamond_problem ), cases do arise in practice where it provides a more natural solution than single inheritance can.
So, is there a way we can simulate multiple inheritance in C# and avoid the diamond problem at the same time?
Proposed Solution
The solution which is usually proposed to deal with the lack of multiple inheritances in C# is 'containment'. This means that the derived class contains (as private fields) objects of each additional parent class and 'wraps' their public members by declaring public members of its own which then delegate to the parent object's members. If any of these members have the same names as existing members of the derived class, then the names are simply changed to avoid conflict.
The following is a simple example of containment though we're going to do the following things slightly differently (you'll see why in Part II of this article).
- Instead of inheriting directly from the additional parent class, we're going to inherit from a private nested class which itself inherits from the parent class.
- We're going to place the nested class and the wrapped methods for the additional parent class in a separate 'partial class' of the derived class.
using System;
class Father
{
public void MethodA()
{
Console.WriteLine("Hello from Father's MethodA");
}
}
class Mother
{
public void MethodA()
{
Console.WriteLine("Hello from Mother's MethodA");
}
public void MethodB()
{
Console.WriteLine("Hello from Mother's MethodB");
}
public static void MethodS() // static method
{
Console.WriteLine("Hello from Mother's static MethodS");
}
public virtual void MethodV() // virtual method
{
Console.WriteLine("Hello from Mother's MethodV");
}
}
partial class Child : Father // add partial modifier
{
public void MethodC()
{
Console.WriteLine("Hello from Child's MethodC");
}
}
partial class Child : Father // contains Mother inheritance stuff
{
private NMother base2; // NMother reference
public Child()
{
base2 = new NMother();
}
// private nested class which inherits from Mother
private class NMother : Mother
{
// overrides the virtual method Mother.MethodV
public override void MethodV()
{
Console.WriteLine("Hello from Child's MethodV");
}
}
// wraps Mother.MethodA but changes name to MethodD to avoid conflict with Father.MethodA
public void MethodD()
{
base2.MethodA();
}
// wraps Mother.MethodB
public void MethodB()
{
base2.MethodB();
}
// wraps static method Mother.MethodS
public static void MethodS() // static method
{
NMother.MethodS();
}
// wraps override of Mother.MethodV
public virtual void MethodV()
{
base2.MethodV();
}
}
class GrandChild : Child
{
// further overrides Mother.MethodV
public override void MethodV()
{
Console.WriteLine("Hello from GrandChild's MethodV");
}
}
class Test
{
static void Main()
{
Child c = new Child();
c.MethodA();
c.MethodB();
c.MethodC();
c.MethodD();
Child.MethodS();
c.MethodV();
c = new GrandChild();
c.MethodV();
Console.ReadKey();
}
}
When you build and run this code, the results should be.
Hello from Father's MethodA
Hello from Mother's MethodB
Hello from Child's MethodC
Hello from Mother's MethodA
Hello from Mother's static MethodS
Hello from Child's MethodV
Hello from GrandChild's MethodV
Conclusion
OK, so far so good. The wrapping code is a bit tedious but we can now effectively inherit public methods from an additional parent class (or as many such classes as we like). However, there are still some gaps in the implementation (for example inheriting protected members) which I'll deal with in Part II of this article.