web-dev-qa-db-ja.com

GoFブックに記載されているインターフェース継承の定義の説明

Gof book の最初の章を読んでいます。セクション1.6では、クラスとインターフェイスの継承について説明します。

クラスとインターフェイスの継承

オブジェクトのクラスとそのタイプの違いを理解することが重要です。オブジェクトのクラスは、オブジェクトの実装方法を定義します。クラスは、オブジェクトの内部状態とその操作の実装を定義します。対照的に、オブジェクトのタイプは、インターフェース(オブジェクトが応答できる要求のセット)のみを参照します。オブジェクトには多くのタイプがあり、異なるクラスのオブジェクトにも同じタイプがあります。

もちろん、クラスとタイプの間には密接な関係があります。クラスはオブジェクトが実行できる操作を定義するため、オブジェクトのタイプも定義します。オブジェクトがクラスのインスタンスであると言うとき、そのオブジェクトがクラスによって定義されたインターフェースをサポートしていることを意味します。

C++やEiffelなどの言語は、クラスを使用してオブジェクトのタイプとその実装の両方を指定します。 Smalltalkプログラムは変数の型を宣言しません。したがって、コンパイラは、変数に割り当てられたオブジェクトのタイプが変数のタイプのサブタイプであることを確認しません。メッセージを送信するには、受信者のクラスがメッセージを実装していることを確認する必要がありますが、受信者が特定のクラスのインスタンスであることを確認する必要はありません。

クラス継承とインターフェイス継承(またはサブタイプ)の違いを理解することも重要です。クラス継承は、別のオブジェクトの実装の観点からオブジェクトの実装を定義します。要するに、それはコードと表現の共有のためのメカニズムです。対照的に、インターフェイスの継承(またはサブタイプ)は、オブジェクトを別のオブジェクトの代わりに使用できる場合を示します。

私はJavaとJavaScriptプログラミング言語に精通しており、ここで説明したC++、Smalltalk、Eiffelのいずれにも精通していません。したがって、ここで説明する概念をJavaのクラスの実行方法にマッピングしようとしています。 、継承とインターフェイス。

これが私がJavaでこれらの概念をどう考えるかです:

Javaでは、クラスは常にそれが生成するオブジェクトの青写真であり、(「オブジェクトが応答できるすべての可能な要求のセット」のように)そのクラスのオブジェクトが所有するインターフェイスが定義されます。オブジェクトのクラスがそれらのインターフェースを実装しているため、コンパイル段階でのみそのクラスのオブジェクトが応答できる要求は、クラス内にあるすべてのメソッドのセットです(このクラスが実装するインターフェース用に実装されたものを含む) )。

私の具体的な質問は次のとおりです。

  1. 3番目の段落で説明したように、Javaの方法はC++に似ていると私は言っていますか。
  2. 最後の段落のインターフェイス継承の意味がわかりません。 Javaインターフェースの継承は、別のインターフェースから拡張された1つのインターフェースです。しかし、Wordinterfaceには、ここで他のオーバーロードされた意味があると思います。 Javaの例では、ここでインターフェイスの継承が何を意味するかを理解できるように、
3
Geek
  1. 3番目の段落で説明するように、JavaクラスはC++に似ています。 Javaインターフェースは別の概念です。
  2. Javaでは、クラスはGoFの意味でのインターフェースと実装の両方を暗黙的に指定します。対照的に、a JavaインターフェイスはGoFの意味でインターフェイスを明示的に指定し、実装を指定しません。どちらの場合も、継承はインターフェイスの継承を意味します。クラス継承の場合にのみ、実装の継承を意味します。 。

区別のより良い例として、クラスがmethod_missingを使用して無関係なオブジェクトをプロキシする方法を理解するのに十分なRuby)を学ぶことを強くお勧めします。これは非常に明確な例を提供します。実装継承なしのインターフェース継承の例(ボーナス、RubyのOOモデルはSmalltalkのモデルと同じですが、構文がより馴染みがあり、本の残りの部分に足を踏み入れることができます。)

2
btilly
  1. はい、Javaクラスはこの点でC++クラスに似ています。
  2. はい、この場合、インターフェースは実際にはJavaおよびC#に存在するinterface言語構造を意味しません。この場合、より抽象的な意味があります。あなたはそれを同一視できると思いますオブジェクトで呼び出すことができるパブリックメソッドとフィールドに。

ここでのクラス継承とは、子クラスがその親の動作を継承する標準のサブタイプを意味します。インターフェイスの継承は、ポリモーフィズムと仮想メソッド呼び出しにはるかに関連しています。これは、子クラスが、親が受け入れて応答できる「メッセージを受け入れて応答できる」ことを意味します。 「オブジェクトを別のオブジェクトの代わりにいつ使用できるかを説明する」全体は、基本的にサブタイプのポリモーフィズムの定義です。

1
Euphoric

このコメントは非常に興味深いものであり、次の質問に積極的に貢献できると思います。

私はかつてJavaユーザーグループミーティングに参加しました。そこではJames Gosling(Javaの発明者)が注目の講演者でした。思い出に残るQ&Aセッション中に、誰かが彼に尋ねました:「できればJavaもう一度、何を変えますか?」「クラスを省略します」と彼は答えた。笑いが収まった後、彼は本当の問題はクラス自体ではなく、むしろ実装継承は関係を拡張します)。インターフェース継承implements Relationship)が望ましいです。可能な限り、実装の継承は避けてください。

https://www.javaworld.com/article/2073649/core-Java/why-extends-is-evil.html

1
ricardoramos

@Euphoricはすでに両方の質問に答えています。私は彼の説明をさらに明確にしたかっただけです。

インターフェイスを継承せずに「クラス継承」を実行することは可能です完全に。 Javaに触れてから5年以上経ちますが、正しく覚えていれば、「保護された」メソッドは、パッケージの外部で継承されると、クラスに対して「プライベート」になります。これで、Java "protected"メンバーはオブジェクトのインターフェイスの一部になりますが、 "private"メンバーはそうではありません(クラスのインスタンスを使用してアクセスできるものはすべて、そのインターフェイスの一部です。これはJavaは "public"および "protected"であると私は信じています)。このシナリオでは、メソッドは継承されます(つまり、-はサブクラス内で独自に使用できます)がサブクラスのインスタンスでメソッドを呼び出すことはできません。したがって、インターフェイスを継承せずにクラスを継承できます。

1
vaibhav