Introduction
There are situations where multiple inheritance is the best (if not the only) choice when designing a certain model for our program or project. C# unfortunately does not support multiple inheritance and so we must look for ways to adapt our design to make possible its implementation. But C# does offer resources and tricks that can be used to simulate multiple inheritance without radically redesigning our class model, with only adding several auxiliary methods and classes and taking one or two precautions while coding them. I propose a design pattern that lets us simulate multiple inheritance in a C# program in a way that produces classes that behave almost like they were really extended from two or more parent classes. We will face classical multiple inheritance problems too and will see how to address them.
Background
Most recent languages like C#, Java, Delphi, have simple inheritance. They don't have multiple inheritance because their designers had to choose between have it in and have all the problems it comes with, or get it out of the language putting away all those problems, and introduce a versatile and less problematic substitute like interfaces and interface inheritance. Multiple inheritance has multiple problems that we will discuss later. But those problems are quite pathological and do not arise in any program in which multiple inheritance could be useful or could be the most appropriate design.
There are traditional ways to emulate multiple inheritance with interface inheritance with more or less success. Let's suppose we have two classes, A
and B
, and we want C
to inherit from both of them.
class A
{
m1();
}
class B
{
m2();
}
class C : A, B
{
m1();
m2();
}
That code is impossible in C#. The following is the classical workaround to deal with this:
class A
{
m1();
}
interface IB
{
m2();
}
class B : IB
{
m2();
}
class C : A, IB
{
B BObject;
m1();
m2() { BObject.m2(); }
}
In this code, we make class B
to implement a new interface named IB
that has identical methods as those of B
. Then class C
inherits from A
and IB
, and uses an internal B
object that replicates B
's m2
method implementation. So C.m2
in fact calls its BObject.m2
method. Then we can say C
now has A
's implementation of m1()
and B
's implementation of m2()
. And we can use C
object wherever we could use A
objects or IB
objects.
But this solution has several problems. One of them is the fact that we can't use C
objects where explicitly B
objects are expected, but only where IB
objects are. So maybe we will have to change all the other code in the project, replacing references to B
objects with references to IB
objects. That will not be a big problem if we are designing the model and can take such decisions. But if the project is dependant on third party code or the standard library (the Framework) then we will be unable to make those modifications. Even more important, if class B
is not ours, but it is from the standard library or from third party code, we can't make it implement our IB
interface. We can't touch it.
The simulated multiple inheritance pattern for C#
We have seen that we cannot simulate multiple inheritance completely using only interfaces and simple inheritance. We need something more, and C# happens to have that. Let's see.
We have these objectives:
- We want class
C
to inherit from classes A
and B
, being able to call their implementation of their methods with no need to rewrite them.
- We want to be able to use
C
objects wherever an A
object or B
object is expected.
- We don't want to modify
A
or B
, for they are untouchable for one or another reason, or we simply don't care.
- We want to instantiate, reference, and use
C
objects just like normal objects.
- We work with parent classes that don't expose
public
fields, but use properties instead. However, this pattern will work even if one of the parent classes (at most) exposes public
fields.
- Of course, this pattern works for three or more parents, not only two.
Here is the basic idea:
We will create two auxiliary classes, Aaux
and Baux
that inherit from A
and B
respectively.
class A
{
m1();
}
class B
{
m2();
}
class Aaux : A
{
m1();
}
class Baux : B
{
m2();
}
Our new class C
won't inherit from A
or B
but have the same methods of both of them. Besides, it will contain two objects: one of type Aaux
and the other of type Baux
. We will call them C.APart
and C.BPart
respectively. C
will use their implementations of m1
and m2
instead of rewriting them.
class C
{
Aaux APart;
Baux BPart;
m1()
{
APart.m1();
}
m2()
{
BPart.m2();
}
}
So every C
object has a pair of A
and B
objects inside. Let's make those objects know who is containing them by adding a reference to the C
object that contains them. We will modify classes Aaux
and Baux
for this purpose:
class Aaux : A
{
C CPart;
m1();
}
class Baux : B
{
C CPart;
m2();
}
And finally we arrive at the final trick. We will redefine the implicit casting operator for class C
, so:
- Whenever an
A
object is expected and a C
object is found, C.APart
is returned.
- Whenever a
B
object is expected and a C
object is found, C.BPart
is returned.
Again, we will redefine the implicit casting operator for class Aaux
so whenever a C
object is expected and an Aaux
object is found, Aaux.CPart
is returned. Identically, we will redefine the implicit casting operator for class Baux
so whenever a C
object is expected and a Baux
object is found, Baux.CPart
is returned.
This is the final look:
class Aaux : A
{
C CPart;
m1();
static implicit operator C(Aaux a)
{
return a.CPart;
}
}
class Baux : B
{
C CPart;
m2();
static implicit operator C(Baux b)
{
return b.CPart;
}
}
class C
{
Aaux APart;
Baux BPart;
m1()
{
APart.m1();
}
m2()
{
BPart.m2();
}
static implicit operator A(C c)
{
return c.APart;
}
static implicit operator B(C c)
{
return c.BPart;
}
}
Now given that code, we can use C
objects wherever an A
or B
object is expected, in addition to where a C
object is expected. The only cost has been adding two extra classes and requiring the parent classes not to expose public
fields.
However, there is another step we can take that will allow us to reduce in on the number of extra classes required and will let one of the parent classes have public
fields. In fact, the class diagram will be even simpler.
We only have to make C
inherit directly from A
, the class which exposes public
fields.
Of course, properties are fully compatible with this pattern, since they behave like methods. So parent classes may have as many public
properties as they wish.
Using the code
Let's see an example. We are a computer dealer that buys computer hardware from major vendors and sells it to end users. However, we often get out of stock and we avoid losing customers by buying from rival computer shops and re-selling to our customers. We are not the only ones with that policy, so other shops often purchase our goods for selling them later. Our program has two arrays - in one of them we keep all our vendors, and in the other we keep all our customers. Rival shops are both vendors and customers. This would be the idea:
class Vendor
{...}
class Customer
{...}
class Shop : Vendor, Customer
{...}
And this could be the final code (it's available in the download):
public class Vendor
{
string id;
public string VendorId
{
get
{
return id;
}
set
{
id = value;
}
}
public Vendor(string vendorId)
{
id = vendorId;
}
public virtual void AskForRessuply()
{
Console.WriteLine("Please ressuply me, vendor "+id+".");
}
}
public class Customer
{
string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public Customer(string customerName)
{
name = customerName;
}
public virtual void SendOrder()
{
Console.WriteLine("Dear "+name+": We are sending your goods.");
}
}
internal class CustomerAux : Customer
{
internal Shop shopPart;
internal CustomerAux(string customerName) : base (customerName)
{
}
static public implicit operator Shop(CustomerAux c)
{
return c.shopPart;
}
}
public class Shop : Vendor {
CustomerAux customerPart;
string address;
public string Address
{
get
{
return address;
}
set
{
address = value;
}
}
public string Name
{
get
{
return customerPart.Name;
}
set
{
customerPart.Name = value;
}
}
public Shop(string vendorId, string customerName, string shopAddress) :
base (vendorId)
{
customerPart = new CustomerAux(customerName);
customerPart.shopPart = this;
address = shopAddress;
}
public virtual void SendOrder()
{
customerPart.SendOrder();
}
static public implicit operator Customer(Shop s)
{
return s.customerPart;
}
}
class EntryPoint
{
static void Main(string[] args)
{
Vendor ibm = new Vendor("32FK-IBM");
Vendor hp = new Vendor("1138-HP");
Customer mrSimpson = new Customer("Mr. Simpson");
Customer mrGates = new Customer("Mr. Gates");
Shop joys =
new Shop("1979-JCS", "Joy's Computer Shop", "123, Fake St.");
Vendor[] vendors = {ibm, hp, joys};
foreach(Vendor ven in vendors)
ven.AskForRessuply();
Customer[] customers = {mrSimpson, mrGates, joys};
foreach(Customer cus in customers)
cus.SendOrder();
Console.ReadLine();
}
}
Points of interest - classical problems
One of the most important problems of multiple inheritance is caused by this situation:
Class A
has the m1()
method. The [ImpA] means that method m1
has been implemented in A
. Classes B
and C
inherit from A
, and both of them redefine method m1
. So class B
has its own implementation of m1
, denoted by [ImpB], and class C
has its own implementation of m1
too, denoted by [ImpC].
Now class D
inherits from B
and C
. The problem is... what implementation of m1
is used while running this code?
D d = new D();
d.m1();
...this code?
B d = new D();
d.m1();
...and this code?
C d = new D();
d.m1();
Languages and compilers supporting multiple inheritance solve this in one way or the other. But this makes compiling, debugging and understanding the code more difficult. Often the version of the implementation of m1
to be run is nearly unpredictable.
However, this pattern solves to certain degree that problem, because we can choose what implementation will be run. Assuming our D
class uses our pattern for simulating multiple inheritance, there will be five different situations:
D
redefines m1
and we always want its implementation to be used: We just have to make D.BPart.m1()
and D.CPart.m1()
to call D.m1()
.
- We always want
B
's implementation: Then we make D.m1()
and D.CPart.m1()
call D.BPart.m1()
.
- We always want
C
's implementation: Then we make D.m1()
and D.BPart.m1()
call D.CPart.m1()
.
- We want
B
's implementation when m1
is called from a B
type variable, C
's implementation when m1
is called from a C
type variable, and D
's new implementation when called from a D
type variable: Just redefine m1
in D
class and let D.BPart
and D.CPart
alone. (This option is not recommendable except when we know what we are doing.)
- We want three new different implementations depending on the type of the variable that references our
D
object at call time: We write different implementations of m1
in D.m1()
, D.BPart.m1()
, and D.CPart.m1()
. (This is even less recommendable than the previous one. But it could be useful for someone.)
Last comment
Multiple inheritance was not included in C# for important reasons. However, I sometimes miss it and that is the reason why I proposed this pattern. I think it may be useful for those who find more advantages in its application than disadvantages. I'd like to see your comments on it, telling problems I didn't see and advices for enhancement.
History
- April 9th, 2005: First version of this article.