C ++、C#、およびAda 95で、動的メソッドバインディングではなく、静的メソッドバインディングを使用することがデフォルトで決定されているのはなぜですか。
実装速度の向上は、抽象化と再利用性の低下に見合う価値がありますか?
C ++、C#、およびAda 95で、動的メソッドバインディングではなく、静的メソッドバインディングを使用することがデフォルトで決定されているのはなぜですか。
実装速度の向上は、抽象化と再利用性の低下に見合う価値がありますか?
一般に、拡張性のために基本クラスを設計する必要があると考えることができます。メンバー関数(C ++ボキャブラリーを使用するため)がオーバーライドされるように設計されていない場合、オーバーライドすることは実際には不可能であり、クラスデザイナーの知識がなければ不可能になる可能性があります。 thinkは実装の詳細であり、事前の通知なしに変更されます。
2つの言語に関するいくつかの追加の考慮事項(私はそれについて書くのに十分なC#を知りません):
選択が異なる場合、Ada95にはAda83との互換性の問題があります。そして、Ada 95のオブジェクトモデル全体を考えると、それを別の方法で行うことは意味がありません(ただし、互換性がオブジェクトモデルの選択の要因であったと考えることができます)。
C ++の場合、パフォーマンスは確かに要因でした。原則を使用しない場合は料金を支払わず、より優れたCが成功に非常に役立ったのと同じようにC++を使用する可能性があります。
明白な答えは、ほとんどの関数が仮想であってはならないからです。AProgrammerが指摘しているように、関数が明示的にオーバーライドされるように設計されていない限り、クラスの不変条件を壊さずに(仮想かどうかにかかわらず)オーバーライドすることはおそらくできません。(たとえば、Javaで作業する場合、final
優れたエンジニアリングの問題として、ほとんどの関数を宣言することになります。C++とAdaは正しい決定を下します。作成者は、関数がオーバーライドされるように設計されていることを明示的に示す必要があります。
また、C ++と(私が思うに)Adaは値のセマンティクスをサポートしています。そして、値のセマンティクスはポリモーフィズムではうまく機能しません。Javaでは、のようなクラスjava.lang.String
はfinal
、それらの値のセマンティクスをシミュレートするためにあります。ただし、多くのアプリケーションプログラマーにとっては、これがデフォルトではないため、気にしないでください。(同様に、クラスが多態的である場合、非常に多くのC ++プログラマーがコピーと割り当てを禁止することを省略します。)
最後に、クラスが多態的であり、継承用に設計されている場合でも、コントラクトは基本クラスで指定され、合理的で強制されます。C ++では、通常、これはpublic
関数が仮想ではないことを意味します。これは、コントラクトを定義および適用するのはパブリック関数であるためです。
Adaについて話すことはできませんが、C ++の場合、C++の設計における2つの重要な目標は次のとおりです。
これらのどちらも、動的バインディングをデフォルトとして選択できなかったことを必ずしも指示するものではありませんが、静的メソッドバインディング(非仮想メンバー関数を意味すると思います)を使用すると、これらの設計目標に「適合」するように見えます。
MichaelBurrの答えの他の3分の2の1つをあげます。
Adaにとって、言語がシステムのプログラミングに適しており、小型のリアルタイム組み込みデバイス(ミサイルや爆弾のCPUなど)で使用できることが重要な設計目標でした。おそらく、動的言語がそのようなことをうまく行うことを可能にする技術があるかもしれませんが、言語が最初に設計された70年代後半から80年代初頭には確かに戻っていませんでした。もちろん、Ada95は、元の言語の基本的な基本設計から根本的に逸脱することはできませんでした。C++がCから逸脱する可能性があります。
そうは言っても、本当に必要な場合は、AdaとC ++(およびC#も同様ですか?)の両方が、動的メソッドバインディング(「動的ディスパッチ」)を実行する方法を提供します。どちらの場合も、ポインタを介してアクセスされますが、IMHOはエラーが発生しやすいものです。また、ソースだけから何が呼び出されているかを正確に判断するのは難しいため、デバッグするのが少し面倒になる可能性があります。ですから、本当に必要でない限り、私はそれを避けます。