处理多重继承的问题之一是接口继承和实现继承之间的区别。
通过使用纯接口,C# 已经有了一个干净的接口继承实现(包括隐式或显式实现的选择)。
如果您查看 C++,对于您在class
声明中冒号后指定的每个类,您获得的继承类型由访问修饰符(private
、、protected
或public
)确定。使用public
继承,你会得到多重继承的全部混乱——多个接口与多个实现混合在一起。通过private
继承,您只需获得实现。"" 的对象class Foo : private Bar
永远不能传递给期望 a 的函数,Bar
因为就好像Foo
该类真的只有一个私有Bar
字段和一个自动实现的委托模式。
纯多重实现继承(实际上只是自动委托)不会出现任何问题,并且在 C# 中会很棒。
至于类的多接口继承,实现该特性有许多不同的可能设计。每种具有多重继承的语言都有自己的规则,即在多个基类中以相同名称调用方法时会发生什么。一些语言,如 Common Lisp(尤其是 CLOS 对象系统)和 Python,有一个元对象协议,您可以在其中指定基类优先级。
这是一种可能性:
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)
在这种情况下,只有第一个列出的类的实现在发生冲突时被隐式继承。必须明确指定其他基类型的类才能获得它们的实现。为了使它更防白痴,编译器可以在冲突的情况下禁止隐式继承(冲突的方法总是需要强制转换)。
此外,您现在可以使用隐式转换运算符在 C# 中实现多重继承:
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;
}
}
但是,它并不完美,因为is
andas
运算符和System.Type.IsSubClassOf()
.