source

"확장 T"는 허용되지만 "실장 T"는 허용되지 않는 이유는 무엇입니까?

factcode 2022. 8. 14. 11:55
반응형

"확장 T"는 허용되지만 "실장 T"는 허용되지 않는 이유는 무엇입니까?

자바에서 항상 "를 사용하는 특별한 이유가 있나요?extends"가 아니라implements" 유형 파라미터의 경계를 정의하기 위해?

예를 들어 다음과 같습니다.

public interface C {}
public class A<B implements C>{} 

는 금지되어 있습니다만,

public class A<B extends C>{} 

정답입니다.그것의 이유는 무엇인가?

클래스가 '실장'인지 '확장'인지에 대한 일반적인 제약조건 언어에는 의미적 차이가 없습니다.제약 조건의 가능성은 '확장'과 '슈퍼'입니다. 즉, 이 클래스가 다른 클래스에 할당 가능한(확장) 클래스로 동작하는지, 아니면 이 클래스에서 할당 가능한(슈퍼) 클래스입니다.

답은 여기 있습니다.

제한된 유형 매개 변수를 선언하려면 유형 매개 변수의 이름을 나열한 후extends키워드 뒤에 상한 [...]가 표시됩니다.이 맥락에서 extensions는 일반적인 의미에서 다음 중 하나를 의미합니다.extends(클래스 등) 또는implements(인터페이스와 같이).

여기에서는 조금 혼란스럽지만 Oracle도 알고 있습니다.

아마도 양쪽(B와 C)에 대해 실장이 아닌 유형만 관련이 있기 때문일 것입니다.이 예에서는

public class A<B extends C>{}

B는 인터페이스로도 사용할 수 있습니다.서브 인터페이스 및 서브 인터페이스를 정의하기 위해 "sub-interface"가 사용됩니다.

interface IntfSub extends IntfSuper {}
class ClzSub extends ClzSuper {}

나는 보통 'Sub extensions Super'를 'Sub는 Super와 비슷하지만 추가 기능을 갖춘다'라고 생각하고, Clz는 Intf를 구현한다'는 'Clz는 Intf의 실현이다'라고 생각한다. 예에서는 B는 C와 같지만 추가 기능이 있습니다.여기서의 기능은, 실현이 아니고, 관련이 있습니다.

기본 유형이 일반 매개 변수이므로 실제 유형이 클래스의 인터페이스일 수 있습니다.고려사항:

class MyGen<T, U extends T> {

또, 클라이언트 코드의 관점에서는, 인터페이스는 클래스와 거의 구별되지 않는 반면, 서브 타입의 경우는 중요합니다.

다음으로 확장이 허용되는 장소와 필요한 기능의 예를 제시하겠습니다.

public class A<T1 extends Comparable<T1>>

어떤 용어를 사용할지는 다소 임의적입니다.어느 쪽이든 될 수 있었다.언어 설계자는 아마도 "확장"을 가장 기본적인 용어로 생각하고 "실장"을 인터페이스의 특별한 경우로 생각했을 것입니다.

하지만 내 생각엔…implements조금 더 말이 되는 것 같아요.매개 변수 유형이 상속 관계가 아니라 모든 하위 유형 관계가 될 수 있다는 것을 더 잘 전달한다고 생각합니다.

Java Glossary도 비슷한 견해를 나타내고 있습니다.

우리는 에 익숙하다.

class ClassTypeA implements InterfaceTypeA {}
class ClassTypeB extends ClassTypeA {}

그리고 이 규칙들을 조금만 벗어나도 우리는 크게 혼란스러워 한다.

유형 바인딩 구문은 다음과 같이 정의됩니다.

TypeBound:
    extends TypeVariable 
    extends ClassOrInterfaceType {AdditionalBound}

(JLS 12 > 4.4). [ Variables ]> 라고 입력합니다.

만약 우리가 그것을 바꾸게 된다면, 우리는 반드시 그것을 추가할 것이다.implements를 구별하다

TypeBound:
    extends TypeVariable 
    extends ClassType {AdditionalBound}
    implements InterfaceType {AdditionalBound}

그리고 결국 두 개의 동일한 처리 조항이 생기게 됩니다.

ClassOrInterfaceType:
    ClassType 
    InterfaceType

(JLS 12 > 4.3). 참조 유형 및 > )

, 우리는 돌볼 필요가 있다.implements일이 더 복잡해질 거야

i i i i i i i i 。extends ClassOrInterfaceType.extends ClassType ★★★★★★★★★★★★★★★★★」implements InterfaceType - 복잡한 개념 안에서. - 단순하게 하기 위해서.가 둘 다 수 있는 입니다.extends ★★★★★★★★★★★★★★★★★」implements소개하기 싫습니다.

<T is ClassTypeA>
<T is InterfaceTypeA>

일일 ~일도 although although although although 。extends인터페이스와 함께 진행되면 혼란이 생깁니다.이것은 더 넓은 용어로, 양쪽의 케이스를 설명하는 데 사용할 수 있습니다.타입의 확장이라는 개념에 맞춰 생각을 조정해 보세요(그렇지 않습니다). 학급 증설 , 아니다 인터페이스의 실장 ) 타입 파라미터를 다른 타입으로 제한하면 그 타입이 실제로 어떤 것이든 상관없습니다.단지 그것이 그것의 상한이고 그것이 그것의 슈퍼타입이라는 것이 중요하다.

<T extensions Comparible>에서 "확장"을 사용하는 것은 데이터 유형 자체가 Comparible을 직접 구현하거나 Comparible을 구현하는 클래스를 확장한다는 약속입니다.Comparible을 실장하는 다른 클래스A의 서브 클래스B를 쓰고 있는 경우가 있습니다.데이터 타입을 선언했을 경우 클래스를 인스턴스화할 때 데이터 타입으로 A 또는B 중 하나를 사용할 수 있습니다.

실제로 인터페이스에서 generic을 사용하는 경우 키워드는 확장됩니다.다음은 코드 예시입니다.

그리팅 인터페이스를 구현하는 클래스는 두 가지가 있습니다.

interface Greeting {
    void sayHello();
}

class Dog implements Greeting {
    @Override
    public void sayHello() {
        System.out.println("Greeting from Dog: Hello ");
    }
}

class Cat implements Greeting {
    @Override
    public void sayHello() {
        System.out.println("Greeting from Cat: Hello ");
    }
}

테스트 코드:

@Test
public void testGeneric() {
    Collection<? extends Greeting> animals;

    List<Dog> dogs = Arrays.asList(new Dog(), new Dog(), new Dog());
    List<Cat> cats = Arrays.asList(new Cat(), new Cat(), new Cat());

    animals = dogs;
    for(Greeting g: animals) g.sayHello();

    animals = cats;
    for(Greeting g: animals) g.sayHello();
}

언급URL : https://stackoverflow.com/questions/976441/why-is-extends-t-allowed-but-not-implements-t

반응형