web-dev-qa-db-ja.com

Javaはプリミティブを必要とするため、実際には純粋なオブジェクト指向プログラミング言語ではありません。なぜですか?

ここで私の質問は、「Javaはプリミティブを必要とするため、実際には純粋なオブジェクト指向プログラミング言語ではない」と言われています。データ型がJava純粋なオブジェクト指向言語になるためにどのように影響するかを知りたいです。 ?

1

「オブジェクト指向」とはさまざまな定義がありますが、それらの定義はすべて、さまざまな角度から問題に取り組んでおり、実際には互いに一致していることがわかります。

「オブジェクト指向」という用語の作成者であるAlan Kayは言います

私にとってのOOPとは、メッセージング、ローカルの保持と保護、および状態プロセスの非表示、およびすべてのものの極端な遅延バインディングのみを意味します。

それを分解しましょう:

  • メッセージング(Smalltalkに精通していない場合は、「仮想メソッドディスパッチ」)
  • 状態プロセスはである必要があります
    • ローカルに保持
    • 保護
    • 隠された
  • すべてのものの極端な遅延バインディング

実装に関しては、メッセージングは​​遅延バインドされたプロシージャコールであり、プロシージャコールが遅延バインドされている場合、設計時にであるかを知ることはできません。呼び出すつもりなので、状態の具体的な表現については何も仮定できません。つまり、実際にはメッセージングに関するものであり、遅延バインディングはメッセージングの実装であり、カプセル化はその結果です。

彼は後に「 大きなアイデアは「メッセージング」 "であると明言し、「オブジェクト指向」という用語は「メッセージ指向」ではなく「オブジェクト指向」と呼んだことを後悔している。重要でないもの(オブジェクト)に焦点を合わせ、本当に重要なもの(メッセージング)から注意をそらします。

前回のOOPSLAで、Smalltalkは構文やクラスライブラリだけでなく、クラスについてでもないことをみんなに思い出させようと、少し苦労したことを少しだけ思い出させてください。多くの人があまり考えられないことに集中するようになるので、私がずっと前にこのトピックのために「オブジェクト」という用語を作ったのは残念です。

大きなアイデアは「メッセージング」です。これがSmalltalk/Squeakの核心です(これは、Xerox PARCフェーズでは完全には完了していませんでした)。日本人は「間にあるもの」を表す小さな単語-ma-を持っています-おそらく最も近い英語の同等物は「間質性」です。優れた拡張可能なシステムを作成するための鍵は、内部のプロパティや動作ではなく、モジュールの通信方法を設計することです。インターネットについて考えてみてください。生きるためには、(a)単一の標準を超えたさまざまな種類のアイデアと実現を可能にし、(b)これらのアイデア間のさまざまな程度の安全な相互運用性を可能にする必要があります。

メッセージングは​​、メタファーとしてもメカニズムとしても、OOにとって基本的です。

あなたが誰かにメッセージを送るならば、あなたは彼らがそれで何をするのか分かりません。あなたが観察できるonlyのことは、彼らの反応です。彼らがメッセージを自分で処理したかどうか(つまり、オブジェクトにメソッドがあるかどうか)、メッセージを他の誰かに転送したかどうか(委任/プロキシ)、理解したかどうかさえわかりません。それがカプセル化のすべてであり、それがOOのすべてです。プロキシが期待どおりに応答する限り、プロキシと本物を区別することさえできません。

「メッセージング」のより「現代的な」用語は「動的メソッドディスパッチ」または「仮想メソッド呼び出し」ですが、それは比喩を失い、メカニズムに焦点を合わせます。

したがって、Alan Kayの定義を見るには、2つの方法があります。それ自体を見てみると、メッセージングは​​基本的に遅延バインディングプロシージャ呼び出しであり、遅延バインディングはカプセル化を意味するため、#1と結論付けることができます。と#2は実際には冗長であり、OOはすべて遅延バインディングに関するものです。

しかし、彼は後で重要なことはメッセージングであると明言したので、別の角度から見ることができます。メッセージングは​​遅れています。さて、メッセージングがonlyの可能性がある場合、#3は自明に当てはまります。1つしかない場合、そのことは遅れています。 、次にすべてのものは遅れてバインドされます。そしてもう一度、カプセル化はメッセージングから続きます。

同様の点は、 データ抽象化の理解について、再考 by William R. Cook およびまた、彼の 「オブジェクト」と「オブジェクト指向」の簡略化された最新の定義の提案

操作の動的ディスパッチは、オブジェクトの本質的な特性です。これは、呼び出される操作がオブジェクト自体の動的プロパティであることを意味します。操作を静的に識別することはできません。また、一般に、特定の要求に応答して実行する操作を正確に実行する方法はありません。これは、常に動的にディスパッチされるファーストクラス関数の場合とまったく同じです。

Smalltalk-72には、オブジェクトすらありませんでした。解析、書き換え、および再ルーティングされたonlyメッセージストリームがありました。最初に登場したメソッド(メッセージストリームを解析および再ルーティングする標準的な方法)、後に登場したオブジェクト(いくつかのプライベート状態を共有するメソッドのグループ)。継承はずっと後になって、クラスは継承をサポートする方法としてのみ導入されました。ケイの研究グループがプロトタイプについてすでに知っていたとしたら、そもそもクラスを導入したことはなかっただろう。

Types and Programming LanguagesのBenjamin Pierceは、オブジェクト指向の定義機能は Open Recursion

つまり、Alan Kayによると、OOはメッセージングがすべてです。WilliamCookによると、OOは動的メソッドディスパッチがすべてです(これは実際には同じことです) )Benjamin Pierceによると、OOはすべてOpenRecursionに関するものです。これは基本的に、自己参照が動的に解決されることを意味します(または、少なくともそれは考える方法です)。つまり、 、メッセージング。

ご覧のとおり、「OO」という用語を作り出した人は、オブジェクトに対してかなり形而上学的な見方をしており、クックはかなり実用的な見方をしており、ピアスは非常に厳密な数学的見方をしています。しかし重要なことは、哲学者、実用主義者、理論家がすべて同意するということです。メッセージングは​​OOの1つの柱です。限目。

彼の論文では、CookはOOPを別の角度から見ています:データ抽象化。現在最も広く使用されている2つのデータ抽象化形式、つまりオブジェクトと抽象データ型の違いを明らかにしています。そして彼は、基本的な違いは、同じ抽象データ型の2つのインスタンスが互いの表現を検査できるのに対し、2つのオブジェクトは同じタイプのインスタンスであっても検査できないことであると述べています。彼はこれをAutognosis(Self-Knowledge、つまりオブジェクトonlyはそれ自体を知っています)、私はXenoagnosticism(Foreign-Not-Knowledge)という用語を好みますが、重要なことはオブジェクトがそれ自体を知っているということではないからです、むしろそれは他のオブジェクトについて知らないということです。

したがって、プリミティブがOOではないのはそのためです。メッセージを送信することによってプリミティブと対話することはなく、プリミティブは相互にカプセル化されず、他のタイプからのみカプセル化されます。つまり、これらはADTであり、オブジェクトではありません。

ただし、Javaにはsecondのものがあり、後者の説明にも当てはまることに注意してください:クラス!はい、同じクラスの2つのインスタンス互いの表現を検査できます!つまり、クラスのインスタンスはnotオブジェクトであり、クラスはオブジェクトを定義しません!これは最初は少し直感に反しているように見えますが、クラスはすべてOOについてですか?まあ、いいえ。OOはオブジェクトについてであり、クラス、それがOOであり、COではない)と呼ばれる理由です。そして、あなたcanはJavaでオブジェクトを持つことができます:同じインターフェースはnotお互いの表現を検査できないため、インターフェースのインスタンスはオブジェクトであり、インターフェースはオブジェクトを記述します。

基本的に、これが意味するのは、プリミティブまたはクラスを型として使用できないことです。型として使用できるのはインターフェイスだけです。具体的にはどういう意味ですか?タイプはどこで発生しますか?つまり、フィールド、静的フィールド、ローカルフィールド、メソッドパラメータ、およびメソッドの戻り値は、型としてインターフェイスのみを持つことができ、汎用型引数、instanceof演算子、およびキャスト演算子は次の場合にのみ使用できます。引数としてのインターフェース。または、反対側から見てください。クラスはファクトリとしてのみ使用できます。つまり、クラス名はnew演算子の直後にのみ表示できます。 (もちろん、プリミティブをタイプとして使用することもできません。)

OOには、言及が必要な別の側面があります。シミュレーション。OOはシミュレーションで生まれました(Simula、現在OOとして特徴付けられる最初の言語はシミュレーション用に設計された言語)、およびOO)の原則の1つは、2つのオブジェクトが動作する限り、オブジェクトに送信するメッセージと、オブジェクトがそれらのメッセージにどのように応答するかだけを観察できることです。同じように、それらは区別できません。つまり、オブジェクトは別のオブジェクトをシミュレートできます。参照を比較すると、シミュレータとシミュレート者の間で、他の点では同じように動作する2つのオブジェクトを区別できるため、参照の同等性はこれを破ります。

したがって、最後に、JavaではOO)ではない3つのことは次のとおりです。

  • プリミティブ
  • クラス
  • ==

そして、OOではないものや、クラスのようなさらに重要なものがあり、それなしでは賢明なJavaプログラムを書くことは不可能なので、合理的にJava OOに関して「不純」。

ただし、「不純」であることについて本質的に「悪い」ことは何もないことに注意してください。たとえば、オブジェクト指向データ抽象化と抽象データ型を使用したデータ抽象化は、異なるトレードオフがあり、補完的であるため、goodを使用できます。両方とも同じ言語で。

(ただし、プリミティブについてはあまり寛容ではないことを認めなければなりません。LISPとSmalltalkコミュニティは、Javaよりずっと前に、「プリミティブ」の高性能と表現のオーバーヘッドの問題を解決し、非常に高性能なSmalltalkのようなものさえありました。 VM開発されたwithinSun、つまりセルフVM。したがって、パフォーマンスに必要なことはなく、作成することもできませんでした。言語にそれを。)

4
Jörg W Mittag