型パラメーターの境界を定義するために「extends
」ではなく、常に「implements
」を使用する特別な理由がJavaにあるのだろうか。
例:
public interface C {}
public class A<B implements C>{}
禁止されていますが
public class A<B extends C>{}
正しい。その理由は何ですか?
ジェネリック制約言語には、クラスが「実装する」か「拡張する」かの間で意味的な違いはありません。制約の可能性は、「extends」と「super」です。つまり、このクラスは他のクラスに割り当て可能に動作する(extends)か、このクラスはそのクラスから割り当て可能(super)です。
答えは here にあります:
制限された型パラメーターを宣言するには、型パラメーターの名前、
extends
キーワード、そのupper bound[…]の順にリストします。このコンテキストでは、extends
(クラスの場合)またはimplements
(インターフェイスの場合)のいずれかを意味する一般的な意味で、extendsが使用されることに注意してください。
そこにあなたはそれを持っています、それは少し混乱します、そしてオラクルはそれを知っています。
おそらく、両側(BとC)には、実装ではなく型のみが関係しているためです。あなたの例では
public class A<B extends C>{}
Bもインターフェイスにすることができます。 「拡張」は、サブインターフェースとサブクラスを定義するために使用されます。
interface IntfSub extends IntfSuper {}
class ClzSub extends ClzSuper {}
私は通常、「Sub extends Super」を「SubはSuperに似ていますが、追加機能がある」と考え、「ClzはIntfを実装します」を「ClzはIntf 'の実現です。あなたの例では、これは一致します:BはCに似ていますが、追加機能があります。ここでは、機能は実現ではなく関連しています。
基本型は汎用パラメーターである可能性があるため、実際の型はクラスのインターフェイスである可能性があります。考慮してください:
class MyGen<T, U extends T> {
また、クライアントコードの観点からは、インターフェイスはクラスとほとんど区別できませんが、サブタイプの場合は重要です。
次に、拡張が許可される場所と、おそらく必要なもののより複雑な例を示します。
public class A<T1 extends Comparable<T1>>
どの用語を使用するかは任意です。どちらの方法でもかまいません。おそらく、言語設計者は、「拡張」を最も基本的な用語として、「実装」をインターフェイスの特殊なケースと考えていたのでしょう。
しかし、implements
はもう少し意味があると思います。パラメータタイプが継承関係にある必要はなく、anyのサブタイプ関係にあることをより伝えていると思います。
Java用語集は、 類似したビュー を表します。
このコンテキストでの「拡張」とは、インターフェイスで実装し、クラスで拡張するようなものです。 詳細はこちら
私たちは慣れています
class ClassTypeA implements InterfaceTypeA {}
class ClassTypeB extends ClassTypeA {}
そして、これらの規則からのわずかな逸脱は、私たちを大きく混乱させます。
型バインドの構文は次のように定義されます
TypeBound:
extends TypeVariable
extends ClassOrInterfaceType {AdditionalBound}
( JLS 12> 4.4。型変数> TypeBound
)
変更する場合は、必ずimplements
ケースを追加します
TypeBound:
extends TypeVariable
extends ClassType {AdditionalBound}
implements InterfaceType {AdditionalBound}
そして、同様に処理された2つの句になります
ClassOrInterfaceType:
ClassType
InterfaceType
( JLS 12> 4.3。参照タイプと値> ClassOrInterfaceType
)
ただし、implements
も処理する必要がありますが、これは事態をさらに複雑にします。
私は、extends ClassOrInterfaceType
とextends ClassType
の代わりにimplements InterfaceType
が使用される主な理由だと思います-複雑な概念の中で物事をシンプルに保つためです。問題は、extends
とimplements
の両方をカバーする適切なWordを持っていないことであり、絶対に紹介したくありません。
<T is ClassTypeA>
<T is InterfaceTypeA>
extends
は、インターフェースと一緒に使用すると混乱を招きますが、より広義の用語であり、両方のケースを説明するために使用できます。 タイプを拡張するという概念に心を合わせてみてください クラスを拡張する、ではない インターフェースの実装)。型パラメーターを別の型で制限し、その型が実際に何であるかは関係ありません。重要なのは、その上限とそのスーパータイプです。