One of the issues with dealing with multiple inheritance is the distinction between interface inheritance and implementation inheritence.
C# already has a clean implementation of interface inheritence (including choice of implicit or explicit implementations) by using pure interfaces.
If you look at C++, the kind of inheritence you get from each class you specify after the colon in the class
declaration is determined by the access modifier (private
, protected
, or public
). With public
inheritence, you get the full messiness of
multiple inheritence--multiple interfaces are mixed with multiple implementations. With private
inheritance, you just get implementation. An object of "class Foo : private Bar
" can never get passed to a function that expects a Bar
because it's as if the Foo
class really just has a private Bar
field and automatically-implemented delegation pattern.
Pure multiple implementation inheritance (which is really just automatic delegation) doesn't present any problems and would be awesome to have in C#.
As for multiple interface inheritence from classes, there are many different possible designs for implementing the feature. Every language that has multiple inheritence has its own rules as to what happens when a method is called with the same name in multiple base classes. Some languages, like Common Lisp (particularly the CLOS object system), and Python, have a meta-object protocol where you can specify the base class precedence.
Here's one possibility:
abstract class Gun
{ public void Shoot(object target) {}
public void Shoot() {}
public abstract void Reload();
public void Cock() { Console.Write("Gun cocked."); }
}
class Camera
{ public void Shoot(object subject) {}
public virtual void Reload() {}
public virtual void Focus() {}
}
//this is great for taking pictures of targets!
class PhotoPistol : Gun, Camera
{ public override void Reload() { Console.Write("Gun reloaded."); }
public override void Camera.Reload()
{ Console.Write("Camera reloaded.");
}
public override void Focus() {}
}
var pp = new PhotoPistol();
Gun gun = pp;
Camera camera = pp;
pp.Shoot(); //Gun.Shoot()
pp.Reload(); //writes "Gun reloaded"
camera.Reload(); //writes "Camera reloaded"
pp.Cock(); //writes "Gun cocked."
camera.Cock(); //error: Camera.Cock() not found
((PhotoPistol) camera).Cock(); //writes "Gun cocked."
camera.Shoot(); //error: Camera.Shoot() not found
((PhotoPistol) camera).Shoot();//Gun.Shoot()
pp.Shoot(target); //Gun.Shoot(target)
camera.Shoot(target); //Camera.Shoot(target)
In this case, only the first listed class's implementation is implicitly inherited in the case of a conflict. The class for other base types must be explicitly specified to get at their implementations. To make it more idiot-proof the compiler can disallow implicit inheritence in the case of a conflict (conflicting methods would always require a cast).
Also, you can implement multiple inheritence in C# today with implicit conversion operators:
public class PhotoPistol : Gun /* ,Camera */
{ PhotoPistolCamera camera;
public PhotoPistol() {camera = new PhotoPistolCamera();}
public void Focus() { camera.Focus(); }
class PhotoPistolCamera : Camera { public override Focus() { }}
public static Camera implicit operator(PhotoPistol p)
{ return p.camera;
}
}
It's not perfect, though, as it's not supported by the is
and as
operators, and System.Type.IsSubClassOf()
.