web-dev-qa-db-ja.com

ミックスインまたは特性は、単純な多重継承よりも優れていますか?

C++には単純な多重継承があり、多くの言語設計ではそれを危険として禁止しています。しかし、RubyやPHPのような一部の言語では、奇妙な構文を使用して同じことを行い、mixinまたはtraitsと呼んでいます。mixin/ traitsの方が難しいと何度も聞いています。単純な多重継承よりも悪用する。

具体的には何が彼らの危険を減らしますか?ミックスイン/トレイトではできませんが、C++スタイルの多重継承では可能なものはありますか?彼らと一緒にダイヤモンドの問題に遭遇することは可能ですか?

これは、多重継承を使用しているように見えますが、それらを使用できるように、それらがミックスイン/特性であるという言い訳をしているだけです。

57
Gherman

完全なクラスで使用する場合、多重継承には多くの問題がありますが、それらはすべてambiguityを中心に展開されます。

あいまいさはいくつかの異なる方法で現れます。

  1. 同じフィールドxを持つ2つの基本クラスがあり、派生型がxを要求する場合、それは何を取得しますか?
    • 2つのx変数の型が一致しない場合は、それを推測できます。
    • それらが同じタイプである場合、それらを同じ変数にマージしようとすることができます。
    • あなたはいつもそれらを奇妙な完全修飾名として公開することができます。
  2. 同じ関数fを持つ2つの基本クラスが同じシグネチャであり、誰かがfを呼び出すと、呼び出されますか?
    • 2つの基本クラスが別の共通の仮想祖先(ダイヤモンド問題)を共有するとどうなるでしょうか。
    • 関数に異なるが互換性のある署名がある場合はどうなりますか?
  3. 2つの基本クラスを持つクラスを構築するとき、基本クラスのコンストラクターのどれが最初に呼び出されますか?あなたがオブジェクトを破壊すると、どれが殺されますか?
  4. オブジェクトをメモリに配置するとき、どのように一貫してそれを行うのですか?
  5. 3つの基本クラスでこれらのすべてのケースをどのように処理しますか? 10?

また、動的ディスパッチ、型推論、パターンマッチングなど、言語が完全なクラスの複数の継承をサポートしている場合に、より難しくなるものについては無視しています。

特性またはミックスイン(またはインターフェース、または...)はすべて、具体的にはlimit型の機能であるため、曖昧さがないように構成されています。彼らはめったに自分自身を所有しません。これにより、2つの変数または2つの関数がないため、型の構成がよりスムーズになります。変数と参照があります。関数と署名。コンパイラは何をすべきかを知っています。

取られる他の一般的なアプローチは、ユーザーにタイプを一度に1つずつ「ビルド」(または混合)させることです。基本クラスが新しい型の同等のパートナーである代わりに、ある型を別の型に追加し、そこにあったものを上書きします(通常、オプションの構文で上書きされたビットの名前を変更したり、再公開したりします)。

ミックスイン/トレイトではできませんが、C++スタイルの多重継承では可能なものはありますか?

言語によっては、通常、関数の実装実装をマージして複数の基本クラスからの変数を格納し、それらを派生型で公開するのが面倒または不可能になります。

彼らと一緒にダイヤモンドの問題に遭遇することは可能ですか?

時々、あなたの言語に基づいてそれほど深刻でないバリエーションがポップアップしますが、通常はありません。特徴の全体的なポイントは、そのようなあいまいさを解消することです。

32
Telastyn