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