1

インターフェイスの多重継承は、一連のクラスからの多重継承よりも達成するのがはるかに難しいのはなぜですか? 大学の問題で困っています。ありがとう

4

4 に答える 4

3

異なるクラスから同じシグネチャを持つ 2 つのメソッドを継承すると、このメソッドを呼び出すときにあいまいさが生じます。解決することはできますが、間違いなく厄介な状況です。

同じメソッド シグネチャを使用して 2 つのインターフェイスを実装しても問題ありません。メソッドを呼び出すときに選択できる実装は 1 つしかないためです。

ダイヤモンド問題は、上記の問題の延長であり、状況をさらに厄介なものにしています。この問題は基本的に、複数の継承をインターフェイスに制限すると解消されます。

于 2012-05-28T10:07:04.267 に答える
0

おそらく粒度のためです。クラスが実装するインターフェイスを選択できます。一方、クラスを拡張すると、クラスの階層全体が自動的に継承されます。

于 2012-05-28T10:04:29.600 に答える
0

少なくとも .net で述べたように、インターフェイス メソッドは、インターフェイス タイプであると宣言されている、またはインターフェイス タイプに制約されているオブジェクトでのみ使用できます。したがって、C1に methodがあり、それぞれが method を宣言するインターフェースおよびFooも実装している場合、ほとんどの場合、 という名前のメソッドが 3 つ存在するという事実は重要ではありません。Intf1Intf2FooFoo

さらに、member を含むinterfaceIDerived1IDerived2inheritの場合、両方のインターフェイスを実装するクラス、または両方のインターフェイスを継承するインターフェイスは、 の定義を 1 つだけ定義します。、、および/または 両方から派生したインターフェースが独自のメンバーを宣言することは可能ですが、そのような定義は から完全に分離されます。派生インターフェイスをキャストして呼び出すと、直接キャストするかどうかに関係なく、常に同じメソッドが生成されます。IBaseFooIBase.FooIDerived1IDerived2FooIBase.FooIBaseFooIBase.FooIBase、または最初に他のインターフェースにキャストします。対照的に、クラスが他の 2 つのクラスから派生し、どちらも共通の基本クラスの同じメンバーをオーバーライドする場合、派生クラスのオブジェクトを基本クラスにキャストしてからそのメンバーを使用しようとするとどうなるかは不明です。 .

ちなみに、あいまいさが生じる状況がいくつかあります。インターフェイスが同じ名前のメンバーを持つ 2 つのインターフェイスを継承する場合、何らかのトリックを使用して、コンパイラが一方を他方よりも優先するようにするか、派生インターフェイスに同じ名前の独自のメンバーを追加してシャドーする必要がある場合があります。どちらもオリジナル。また、ジェネリックを使用する場合、ジェネリック型を制約して複数のインターフェイスを実装し、クラスから継承することもできます。これが行われると、インターフェースやクラスがメンバー名を共有する場合、あいまいさが生じる可能性があります。

于 2012-05-29T22:48:39.127 に答える
0

考えられる理由は 2 つあります。1.) ダイヤモンドの問題 (ウィキペディアで調べてください)、2.) オブジェクトの同一性。

class A { }
class B { }
class C : A, B { }

C * c = new C ();
A * a = c;
B * b = c;

そうすると、単に a == b をテストするだけでは、オブジェクトの同一性を検証できません。この機能を言語で実装しようとすると、バックグラウンドで単純なポインター演算を使用することはできません。クラスへのすべてのアクセス (複数の継承とは無関係) は、a と b が通常のポインターでなくなるため、はるかにコストがかかります。

A と B がインターフェイスである場合、問題について知っている (継承されることがわかっている) ため、インターフェイスへのアクセスをクラスへのアクセスとは異なる方法で扱うことができます。

ところで、複数クラスの継承はそれほど難しくありません。

編集:追加。そして、それは概念的な問題をもたらします:

class C0 { virtual int meth { return 0; } };
class C1 : C0 { virtual int meth { return 1; } };
class C2 : C1, C0 { }

定義すると

C2 * c2 = new C2;

どうしたら良い

((C1 *) c2)->meth()

((C0 *) c2)->meth()

人々を混乱させないために戻る?(編集: この例を修正しました。)

于 2012-05-28T10:19:56.060 に答える