1. ホーム
  2. ジャバスクリプト

[解決済み】プロトタイプベース継承とクラスベース継承の比較

2022-04-07 13:15:07

質問

JavaScriptでは、すべてのオブジェクトはインスタンスであり、同時にクラスでもあります。継承を行うには、任意のオブジェクトのインスタンスをプロトタイプとして使用することができます。

PythonやC++などでは、クラスとインスタンスが別々の概念として存在します。継承を行うには、基底クラスを使って新しいクラスを作成し、そのクラスを使って派生インスタンスを生成する必要があります。

JavaScriptはなぜこのような方向性(プロトタイプベースのオブジェクト指向)になったのか、従来のクラスベースのOOに対するプロトタイプベースのOOの利点(と欠点)は何か。

どうやって解決するの?

ここには約100の用語の問題があり、そのほとんどは誰か(あなたではない)が自分のアイデアを「ベスト」と思わせようとしていることに起因しています。

すべてのオブジェクト指向言語は、いくつかの概念を扱うことができる必要があります。

  1. データメンバーとメンバー関数、あるいはデータとメソッドなど、さまざまな名前で知られているデータに対する操作とデータのカプセル化。
  2. 継承とは、これらのオブジェクトは、他のオブジェクトのセットと同じであることを示す能力である。
  3. ポリモーフィズム ("many shapes") は、オブジェクトがどのメソッドを実行するかを自ら決定するもので、リクエストを正しくルーティングするために言語に依存することができます。

さて、比較についてですが。

まず、「クラス」と「プロトタイプ」の違いについてです。 このアイデアはもともとSimulaで始まりました。クラスベースのメソッドでは、各クラスは同じ状態空間(「可能な値」とも言います)と同じ操作を共有するオブジェクトの集合を表し、それによって等価クラスを形成していました。 Smalltalkを振り返ると、クラスを開いてメソッドを追加することができるので、これは事実上Javascriptでできることと同じです。

その後のOO言語では、静的型チェックを使えるようにしたかったので、コンパイル時に固定されたクラスセットという概念が生まれました。 オープンクラス版では、より柔軟性があり、新しいバージョンでは、テストが必要だったいくつかの種類の正しさをコンパイラでチェックできるようになったのです。

クラスベースの言語では、コンパイル時にコピーが行われます。 プロトタイプ言語では、操作はプロトタイプのデータ構造に格納され、実行時にコピーされ変更されます。 しかし、抽象的には、クラスは、同じ状態空間とメソッドを共有するすべてのオブジェクトの等価クラスであることに変わりはない。 プロトタイプにメソッドを追加することは、事実上、新しい等価クラスの要素を作ることになるのです。

さて、なぜそうするかというと、主に実行時にシンプルで論理的でエレガントなメカニズムになるからです。 または 新しいクラスを作成するには、単にディープコピーを実行して、すべてのデータとプロトタイプのデータ構造をコピーする必要があります。 このとき、継承とポリモーフィズムはほぼ無償で手に入ります:メソッド検索 常に は、名前を指定してメソッドの実装を辞書に問い合わせることである。

Javascript/ECMAスクリプトに行き着いた理由は、基本的に、10年前にこの問題に着手したとき、私たちが扱うコンピュータはそれほど高性能ではなく、ブラウザもそれほど洗練されていなかったからです。 プロトタイプベースの方法を選択することで、オブジェクト指向の望ましい特性を維持しながら、インタプリタを非常にシンプルにすることができました。