2016-09-20 3 views
1

다음 코드 :왜이 대체 메서드 선언이 컴파일 오류를 생성합니까?

class Parent { 
    public void method(List parameter){ 
    } 
} 

class Child extends Parent { 

    public void method(List<String> parameter) { 
    } 
} 

다음과 같은 오류와 함께 컴파일에 실패 :

Parent.java:12: error: name clash: method(List<String>) in Child and method(List) in Parent have the same erasure, yet neither overrides the other 
    public void method(List<String> parameter) { 
       ^
1 error 

하지만 §8.4.8.1에 JLS8 말하는 것을 확인하고 있습니다 :

An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff all of the following are true:

...

The signature of mC is a subsignature (§8.4.2) of the signature of mA.

...

그리고 §8.4.2에서 다음과 같이 말합니다 :

The signature of a method m1 is a subsignature of the signature of a method m2 if either:

...

the signature of m1 is the same as the erasure (§4.6) of the signature of m2.

그리고이 경우 원래의 메서드 선언과 재정의 된 메서드 선언은 모두 동일한 삭제 기능을 갖기 때문에 컴파일이 실패하는 이유는 무엇입니까?

+3

'List '는'List'의 삭제가 아니므로 인용 한 스펙에 따르면 서브 서명이 아닙니다. 나는 당신이'm1'과'm2'을 섞은 것 같아요. – 4castle

+0

그들은 둘 다'List '에 지워지는 유형으로 간주되지 않습니까? –

+1

둘 다'List'에 지워지지만 여러분이 인용 한 스펙은 그들이 공통적으로 지우는 지에 관한 것이 아니라 서브 클래스의 메소드가 수퍼 클래스의 메소드 삭제인지 여부에 관한 것입니다. 부모 클래스가'List '이고 서브 클래스가'List'이면, 괜찮을 것입니다. – 4castle

답변

2

소거 후에는 List (원하는 경우 List<Object>) 만 있습니다. 난 당신이 같은 삭제

class Parent<T> { 
    public void method(List<T> parameter){ 
    } 
} 

class Child extends Parent<String> { 
    public void method(List<String> parameter) { 
    } 
} 
+0

OP가 컴파일러 오류가 아니어야하는 이유와 비슷한 경우를 만들었 기 때문에 귀하의 첫 번째 진술에 대한 대답이 확실하지 않습니다. – 4castle

+0

실제 상위 클래스는 레거시 라이브러리에 속하지만 어쨌든 실제로 솔루션을 찾고있는 것이 아니라 컴파일러가 그런 식으로 행동해야하는 이유입니다. –

+0

@JaimeHablutzel 레거시 코드 (예 : 여기에있는 것)가 제네릭 형식 (거의 전적으로 컴파일 타임 형식 검사 시스템)을 추가하여 계속 작동합니다. 이 경우 –

2

And in this case both the original and the overriding method declarations have the same erasure, so why the compilation fails?

같은 일반적인 Parent를 원 충분하지 않다 생각합니다. 인용 한 JLS 섹션을 다시 한 번 살펴보십시오.

The signature of a method m1 is a subsignature of the signature of a method m2 if either:

...

the signature of m1 is the same as the erasure (§4.6) of the signature of m2.

그건 지우개가 같아야한다는 말은 아닙니다. 즉, 의 서명은 m2의 인 이어야합니다. 여기서 m1의 서명을 삭제하지 않습니다.

+0

'클래스 부모 { 공극 방법 (목록 매개 변수) { } }는 클래스 하위 상위 연장 { 공극 방법 (목록 매개 변수) { } } (M1)의 특성이 동일하다 '컴파일해야 m2의 서명을 지우지 만 그렇지 않습니다. –

+1

@JaimeHablutzel : m1과 m2가 다른 방법입니다. – user2357112

+0

m1과 m2가 올바른 방법을 말하는 것이었지만, 앞의 예에서의 문제는'List '에 대한 타입 지우는'List '이 아니라'List'라고합니다.'(M1)는 m2'의 서명의 삭제와 동일하고'제대로 클래스의 부모 { 무효 방법 (목록 foo는) { } } 클래스 자식이 부모 { 무효 방법 (확장 작동 할 때 다음의 예는 명확히 목록 표시 줄) { } } '. –

관련 문제