2012-07-10 3 views
0
public abstract class AbstractClass 
{ 
    public abstract void AbstractClassMethod(); 
} 


public class DerivedClass extends AbstractClass { 

    @Override 
    public void AbstractClassMethod() { 
     // TODO Auto-generated method stub 

    } 

} 



public interface InterfaceObject 
{ 
    public void InterfaceObjectMethod(AbstractClass oAbstractClass); 
} 



public class TestAbstractParam implements InterfaceObject { 

    @Override 
    public void InterfaceObjectMethod(AbstractClass oAbstractClass) { 
     // TODO Auto-generated method stub 

    } 

} 



public class TestDerivedParam implements InterfaceObject { 

    @Override 
    public void InterfaceObjectMethod(DerivedClass oDerivedClass) { 
     // TODO Auto-generated method stub 

    } 

} 

TestDerivedParam 클래스를 컴파일하는 동안 오류가 발생합니다. 누구든지이 이유를 설명해 주시겠습니까? 보다 구체적으로 말하면, 메소드가 기본 유형을 예상하는 하위 유형 매개 변수를 허용하지 않는 이유는 무엇입니까? 감사합니다. TestDerivedParam에서기본 클래스 객체를 예상하는 파생 클래스 객체 전달

+1

자바를 언급하면서 * 기본 클래스 *라는 용어를 사용하지 마십시오. 언젠가는 사용 되긴하지만 그것은 자바에만 국한된 것이 아닙니다. 당신은 * 수퍼 클래스 *라는 용어를 사용해야합니다. – Lion

+0

감사의 사자! 나는 지금부터 수퍼 클래스라는 용어를 사용하겠다. – Austin

+0

btw, 나는 추상적 클래스를 참조 할 때 특히 "기본 클래스"라는 용어를 사용한다. – Bohemian

답변

1

있어서

public void InterfaceObjectMethod(DerivedClass oDerivedClass) { 

InterfaceObject에서 동일하지

같은
public void InterfaceObjectMethod(AbstractClass oAbstractClass); 

이다.

@Override 주석을 사용하고 있지만 동일한 방법 서명을 사용하고 있지 않습니다. 방법은 기본 유형을 기대하고 하위 유형 매개 변수를 허용하지 못할 이유


은보다 구체적으로, 문제는?

public class Fruit { } 

public class Apple extends Fruit { } 

public class Banana extends Fruit { } 

모두 AppleBananaFruit하지만 AppleBanana하지 않고 BananaApple되지 않습니다 :

아래의 예를 참조하십시오. 따라서, Apple을 기대하는 사람에게 실제로 Banana을 줄 수는 없지만, 단지 Fruit을 기대하는 사람에게 Banana 또는 Apple을주는 것이 유효합니다.

그래서, 그것이 경우

public void method(Apple apple) { 

이 있기 때문에, 그 다음을 의미로

public void method(Fruit fruit) { 

가 동일한 서명이없는 위

public void method(Banana banana) { 
과 같은 서명이

그리고 메서드를 재정의 (구현)하는 동안 서명이 일치해야합니다.

+0

감사합니다. @Bhesh. 그러나 파생 클래스는 수퍼 클래스의 모든 내용을 가지고 있습니다. 그렇다면 수퍼 클래스 대신 패스 할 수없는 이유는 무엇입니까? 그것은 유형 캐스팅이나 그런 것들이 필요합니까. 나는 이유에 대해 명확하지 않다. – Austin

+0

@ user1513795 : 업데이트를 참조하십시오. –

+0

감사합니다. @BheshGurung. 귀하의 설명은 매우 간단하고 이해하기 쉽습니다. 다시 한 번 감사드립니다! – Austin

0

메서드의 서명을 변경하면 Java는 동일한 이름과 다른 매개 변수를 사용하여 기존 메서드를 "오버로드"하는 것으로 가정 할 수 있습니다.

@Override 
public void InterfaceObjectMethod(AbstractClass oDerivedClass) { 
    // TODO Auto-generated method stub 
} 

public void InterfaceObjectMethod(DerivedClass oDerivedClass) { 
    InterfaceObjectMethod((AbstractClass)oDerivedClass); 
} 

이 두 번째 방법은 책임 단순히 실제 상속 방법에 요청을 전달하는 다리의 방법이 될 것이다 :

당신은 대안 다리 방법을 사용할 수 있습니다. 보시다시피 브리지 메서드는 오버로드가 아닌 오버로드입니다.

또 다른 옵션은 제네릭을 사용하는 것입니다.

interface InterfaceObject<T extends AbstractClass> 
{ 
    public void InterfaceObjectMethod(T oAbstractClass); 
} 


class TestAbstractParam implements InterfaceObject<AbstractClass> { 

    @Override 
    public void InterfaceObjectMethod(AbstractClass oAbstractClass) { 
     // TODO Auto-generated method stub 

    } 
} 

class TestDerivedParam implements InterfaceObject<DerivedClass> { 

    @Override 
    public void InterfaceObjectMethod(DerivedClass oDerivedClass) { 
     // TODO Auto-generated method stub 

    } 
} 

궁극적으로 제네릭 버전은 첫 번째 옵션과 정확히 동일합니다. 즉, 브리지 메소드가 컴파일러에 의해 종합적으로 생성됩니다. 클래스를 디 컴파일하면 정확히 알 수 있습니다.

관련 문제