私は自分のプログラミング言語を開発しています。これint x = 1;
は、クラウド向けではない汎用言語(デスクトップ用の静的型付けPythonなど)です。
継承やMixinsを許可しないことは問題ないと思いますか?(ユーザーが少なくともインターフェースを持っている場合)
例: Google Go、継承を許可しないことでプログラミングコミュニティに衝撃を与えたシステム言語。
私は自分のプログラミング言語を開発しています。これint x = 1;
は、クラウド向けではない汎用言語(デスクトップ用の静的型付けPythonなど)です。
継承やMixinsを許可しないことは問題ないと思いますか?(ユーザーが少なくともインターフェースを持っている場合)
例: Google Go、継承を許可しないことでプログラミングコミュニティに衝撃を与えたシステム言語。
回答:
実際、継承の使用は(とりわけ)密結合につながるため、次善の策は次善策であることがますますわかります。
実装の継承は、常にインターフェイスの継承と構成で置き換えることができます。より最近のソフトウェア設計では、構成を優先して、継承を使用する方向が次第に少なくなる傾向があります。
そのため、はい、特に継承を提供しないことは完全に有効であり、流行の設計決定において非常に重要です。
ミックスインは、他の一方で、(まだ)でも主流の言語機能はなく、言語か「ミックスイン」と呼ばれる機能を提供は、多くの場合、それによって非常に異なるものを理解しています。それを提供するかどうかはお気軽に。個人的にはとても便利だと思いますが、正しく実装するのはとても難しいかもしれません。
言語のセマンティクスの残りの部分も無意味であることを考慮せずに、継承(または実際には単一の機能)が必要かどうかについての推論。あなたは真空で議論しています。
必要なのは、一貫した言語設計哲学です。言語は、設計された問題をエレガントに解決できる必要があります。これを達成するためのモデルは、継承を必要とする場合と必要としない場合がありますが、全体像がないとこれを判断するのは困難です。
たとえば、言語にファーストクラスの関数、部分的な関数の適用、ポリモーフィックなデータ型、型変数、ジェネリック型がある場合、従来のOOP継承と同じ基本をカバーしていますが、異なるパラダイムを使用しています。
レイトバインディング、動的型付け、プロパティとしてのメソッド、柔軟な関数引数、およびファーストクラスの関数がある場合も、同じ根拠をカバーしますが、ここでも、異なるパラダイムを使用します。
(概説されている2つのパラダイムの例は、読者のための演習として残しています。)
だから、あなたが望む意味論の種類について考え、それらをいじって、継承なしでそれらが十分かどうか確かめてください。そうでない場合は、継承をミックスに投入するか、他に何かが欠けていると判断する可能性があります。
はい。
特に言語が動的に型付けされている場合は、継承を許可しないことは問題ないと思います。委任や構成などにより、同様のコードの再利用を実現できます。例えば、私はいくつかの適度に複雑なプログラムを書かれている-大丈夫、ではないという複雑な:) - JavaScriptで任意の継承なし。基本的に、オブジェクトを代数的データ構造として使用し、いくつかの関数をメソッドとして付加しました。これらのオブジェクトを操作するメソッドではない関数もたくさんありました。
動的な型付けがある場合(私がそうしていると仮定しています)、継承なしで多態性を持つこともできます。また、実行時にオブジェクトに任意のメソッドを追加することを許可する場合、ミックスインなどはそれほど必要ありません。
別のオプション-私は良いと思います-はJavaScriptをエミュレートしてプロトタイプを使用することです。これらはクラスよりも単純ですが、非常に柔軟です。考慮すべきことだけです。
だから、すべて言った、私はそれのために行きます。
はい、継承を省略することは完全に合理的な設計上の決定です。
実装の継承を削除するのには非常に良い理由があります。非常に複雑でコードの保守が困難になる可能性があるためです。私は、継承は(通常、ほとんどのOOP言語で実装されているため)継承を誤った機能であると見なすこともできます。
たとえば、Clojureは実装の継承を提供せず、同じ結果をよりきれいに達成するために使用できる直交機能(プロトコル、データ、関数、マクロ)のセットを提供することを好みます。
ここで私は非常にリッチヒッキーは(継承を含む)プログラミング言語での複雑さの根本的な原因を特定し、この一般的なトピック、上の啓発およびそれぞれの提示する代替案発見したビデオだ:シンプルで簡単に作られました
VB6クラスが継承(インターフェイスのみ)をサポートしていないという事実に初めて遭遇したとき、それは本当に私を苛立たせました(そして今でもサポートしています)。
ただし、これが非常に悪い理由は、コンストラクターパラメーターもなかったため、通常の依存性注入(DI)を実行できなかったためです。DIがある場合、継承よりも構成を優先するという原則に従うことができるため、継承よりも重要です。それはとにかくコードを再利用するためのより良い方法です。
でも、Mixinsを持っていないのですか?インターフェースを実装し、そのインターフェースのすべての作業を依存性注入を通じてオブジェクトセットに委任する場合は、Mixinsが理想的です。それ以外の場合は、すべてのボイラープレートコードを記述して、すべてのメソッドやプロパティを子オブジェクトに委任する必要があります。私はそれを(C#のおかげで)たくさんやっていました。
別の答えに同意しない場合:いいえ、必要な機能と互換性がない場合は機能を破棄します。Java(およびその他のGCで使用されている言語)は、型の安全性をさらに必要としていたため、明示的なメモリ管理を廃止しました。Haskellは、方程式の推論と派手なタイプをもっと必要としていたので、突然変異を捨てました。Cでさえ、コンパイラの最適化をもっと必要としていたため、特定の種類のエイリアシングやその他の動作を破棄(または違法と宣言)しました。
だから問題は:継承以上のものは何ですか?
free
/ delete
操作はあなたに無効参照する機能を提供します。型システムが影響を受けるすべての参照を追跡できない限り、その言語は安全ではありません。特に、CもC ++もタイプセーフではありません。どちらかを妥協して(線形型や割り当て制限など)、同意させることができるのは事実です。正確には、Javaは特定の単純な型システムと無制限の割り当てを伴う型安全性を求めていたと私は言ったはずです。
null
参照を)。禁止free
かなり任意の追加の制限です。要約すると、言語がタイプセーフかどうかは、言語よりもタイプセーフの定義に依存します。
T
参照はnull
、拡張するクラスのオブジェクトまたはオブジェクトのいずれかを参照しますT
。null
醜いですが、上の操作は、null
上記の型不変式を壊すのではなく、明確に定義された例外をスローします。C ++とのコントラスト:を呼び出した後delete
、T*
ポインタは、もはやが保持していないことをメモリを指してT
オブジェクトを。さらに悪いことに、割り当てでそのポインターを使用してフィールド割り当てを行う場合、たまたま近くのアドレスに配置されただけの場合、別のクラスのオブジェクトのフィールドを完全に更新する可能性があります。これは、用語の有用な定義によるタイプセーフではありません。
番号。
基本言語機能を削除したい場合は、その機能が絶対に必要ではない(または不当に実装が難しく、ここでは適用されない)ことを普遍的に宣言しています。そして、「決して」はソフトウェア工学における強い言葉です。そのような発言を行うには、非常に強力な正当化が必要になります。
厳密にC ++の観点から言えば、継承は主に2つの目的で役立ちます。
要点1については、あまりアクロバットにふけることなくコードを共有する方法がある限り、継承は不要です。ポイント2については、Javaの方法を使用して、この機能を実装するためのインターフェースを要求できます。
継承を削除する利点は
このトレードオフは、主に「Dont Repeat Yourself」と柔軟性と、もう一方の問題回避との間で生じます。個人的には、他の開発者が問題を予測するのに十分なほど賢くないかもしれないので、継承がC ++から移行するのを嫌うでしょう。
継承やMixinsを許可しないことは問題ないと思いますか?(ユーザーが少なくともインターフェースを持っている場合)
実装の継承やミックスインなしで多くの非常に便利な作業を実行できますが、ある種のインターフェイスの継承、つまりオブジェクトがインターフェイスAを実装するかどうかを宣言し、それからBもインターフェイスする必要があることを宣言する必要があるかどうか疑問に思います(つまり、 AはBの特殊化であるため、型の関係があります)。一方、結果のオブジェクトは、両方のインターフェースを実装していることを記録するだけでよいので、それほど複雑ではありません。すべて完全に実行可能です。
ただし、実装の継承がないことには明らかな欠点が1つあります。クラスの数値インデックス付きvtableを構築できなくなるため、すべてのメソッド呼び出しに対してハッシュ検索を実行する必要があります(またはそれらを回避するための賢い方法を見つけ出す必要があります)。このメカニズムを通じて基本的な値(たとえば、数値)をルーティングする場合、これは困難な場合があります。非常に優れたハッシュの実装でさえ、すべての内部ループで複数回ヒットする場合、高額になる可能性があります。