多重継承を扱う際の問題の 1 つは、インターフェイスの継承と実装の継承の違いです。
C# には、純粋なインターフェイスを使用することにより、インターフェイスの継承 (暗黙的または明示的な実装の選択を含む) のクリーンな実装が既にあります。
C++ を見ると、宣言のコロンの後に指定するクラスごとに、取得する継承の種類がアクセス修飾子 ( 、、または)class
によって決まります。継承を使用すると、複数の継承の完全な混乱が発生します。複数のインターフェイスが複数の実装と混在しています。継承では、実装を取得するだけです。" " のオブジェクトは、 を期待する関数に渡されることはありません。これは、クラスが実際にはプライベートフィールドと自動的に実装される委譲パターンを持っているかのようだからです。private
protected
public
public
private
class Foo : private Bar
Bar
Foo
Bar
純粋な複数実装の継承 (実際には自動委譲にすぎません) には問題がなく、C# で実現できれば素晴らしいものです。
クラスからの複数のインターフェイスの継承に関しては、機能を実装するためのさまざまな設計が考えられます。多重継承を持つすべての言語には、メソッドが複数の基本クラスで同じ名前で呼び出されたときに何が起こるかについて、独自の規則があります。Common Lisp (特に CLOS オブジェクト システム) や Python などの一部の言語には、基本クラスの優先順位を指定できるメタオブジェクト プロトコルがあります。
1 つの可能性を次に示します。
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
演算子and でサポートされていないため、完全ではありませんSystem.Type.IsSubClassOf()
。