関数型プログラミングなどのさまざまなプログラミングパラダイムについて学べば学ぶほど、継承やポリモーフィズムなどのOOPコンセプトの知恵に疑問を持ち始めます。私は最初に学校での継承とポリモーフィズムについて学びましたが、当時、ポリモーフィズムは簡単な拡張性を可能にする汎用コードを書く素晴らしい方法のように思えました。
しかし、カモタイピング(動的および静的の両方)および高次関数などの機能的特徴に直面して、継承とポリモーフィズムを、オブジェクト間の脆弱な一連の関係に基づいて不必要な制限を課すように見始めました。多態性の背後にある一般的な考え方は、関数を一度書くだけで、後で元の関数を変更せずにプログラムに新しい機能を追加できるということです。必要なメソッドを実装する別の派生クラスを作成するだけです。
しかし、これは、Pythonのような動的言語であろうと、C ++のような静的言語であろうと、アヒルの型付けによって達成するのがはるかに簡単です。
例として、次のPython関数とそれに続く静的なC ++の機能を考えてみましょう。
def foo(obj):
obj.doSomething()
template <class Obj>
void foo(Obj& obj)
{
obj.doSomething();
}
OOPに相当するものは、次のJavaコードのようなものです。
public void foo(DoSomethingable obj)
{
obj.doSomething();
}
もちろん、大きな違いは、Javaバージョンが機能する前に、インターフェイスまたは継承階層を作成する必要があることです。したがって、Javaバージョンはより多くの作業を必要とし、柔軟性が低くなります。さらに、ほとんどの実際の継承階層はやや不安定であることがわかりました。シェイプとアニマルの不自然な例を見てきましたが、現実の世界では、ビジネス要件の変更と新しい機能の追加に伴い、「is-a」関係を実際に伸ばす前に作業を完了することは困難です。サブクラス、または階層をリモデリング/リファクタリングして、新しい要件に対応するために、さらに基本クラスまたはインターフェイスを追加します。アヒルのタイピングでは、モデリングのことを心配する必要はありません- 必要な機能を心配するだけです。
しかし、継承とポリモーフィズムは非常に人気があるため、拡張性とコードの再利用のための支配的な戦略と呼ぶのは誇張ではないでしょうか。それでは、なぜ継承とポリモーフィズムはそれほど成功しているのでしょうか?継承/ポリモーフィズムがアヒルのタイピングよりも優れているいくつかの重大な利点を見落としていますか?
obj
があります。doSomething
メソッドがないとどうなりますか?例外が発生しましたか?何も起こりませんか?