Grrr .. 抽象サブタイピングには仮想継承を使用する必要があります。OO の設計原則に従うのであれば、選択の余地はまったくありません。そうしないと、他のプログラマーが他のサブタイプを派生させることができなくなります。
最初に抽象化の例を示します。基本抽象化 A があります。サブタイプ B を作成したいと考えています。サブタイプは必ず別の抽象化を意味することに注意してください。抽象的でない場合は、型ではなく実装です。
ここで、別のプログラマーがやって来て、A のサブタイプ C を作成したいと考えています。クールです。
最後に、さらに別のプログラマーがやってきて、B と C の両方である何かを欲しがっています。もちろん、それも A です。これらのシナリオでは、仮想継承が必須です。
以下は実際の例です: コンパイラからのデータ型のモデリング:
struct function { ..
struct int_to_float_type : virtual function { ..
struct cloneable : virtual function { ..
struct cloneable_int_to_float_type :
virtual function,
virtual int_to_float_type
virtual cloneable
{ ..
struct function_f : cloneable_int_to_float_type {
ここで、function
は関数をint_to_float_type
表し、int から float までの関数で構成されるサブタイプを表します。Cloneable
関数を複製できる特別なプロパティです。function_f
具体的な(非抽象)関数です。
function
私が最初に仮想ベースを作成しなかった場合、int_to_float_type
ミックスインできなかったことに注意してくださいcloneable
(逆もまた同様です)。
一般に、「厳密な」OOP スタイルに従う場合は、常に抽象化のラティスを定義してから、それらの実装を派生させます。抽象化にのみ適用されるサブタイプと実装を厳密に分離します。
Java では、これが強制されます (インターフェイスはクラスではありません)。C++ ではそれは強制されておらず、パターンに従う必要はありませんが、それを認識しておく必要があります。また、作業しているチームまたは作業しているプロジェクトが大きくなるほど、その理由は強くなります。あなたはそれから離れる必要があります。
Mixin 型付けには、C++ で多くのハウスキーピングが必要です。Ocaml では、クラスとクラス型は独立しており、構造 (メソッドを所有するかどうか) によって一致するため、継承は常に便利です。これは、実際には名目上のタイピングよりもはるかに使いやすいです。ミックスインは、名目上の型付けのみを持つ言語で構造型付けをシミュレートする方法を提供します。