2010-03-19 5 views
2

아래 코드에서 b1.subtract()가 실패하는 이유는 무엇입니까? 그 이유를 설명해주세요. 즉, 그 메소드를 호출하는 동안 JVM에서 어떤 일이 일어나는지.런타임/컴파일 시간 다형성

class Base { 

public void add() { 
System.out.println("Base ADD"); 
} 

} 

class Child extends Base { 

public void add(){ 
System.out.println("Child ADD"); 
} 

public void subtract() { 
System.out.println("Child Subtract"); 
} 

} 

class MainClass { 

public static void main(String args[]) { 

Base b1 = new Base(); 
Base b2 = new Child(); 

Child b3 = new Child(); 

b1.add(); 

b2.subtract(); // ?????????**previously it was b1.subtract and its wrong 

b2.add(); 
b3.subtract(); 

} 

} 
+0

실패하면 무엇을 의미합니까? 위의 코드는 컴파일 오류를 발생시킵니다. b1은 Base 유형으로 선언되고 "Base"클래스는 "subtract"라는 이름으로 메소드가 없습니다. – sateesh

답변

7

제목에 따라 코드가 실제로 b2.subtract() 인 것을 전제로합니다. Going with :

현재 b2는 Child의 인스턴스이며 코드에서 항상 Child의 인스턴스가된다는 것을 쉽게 알 수 있지만 Java는 정적으로 입력되므로 사용을 허용 할 수 없습니다 실제 클래스의 메소드, 선언 된 클래스.

이 예제를 고려하십시오

Base b2 = Math.random() > 0.5 ? new Base() : new Child(); 
b2.subtract();

지금은 B2 단지가 될 수 있기 때문에 당신은 분명 가능 (아이의 모든 메소드를 호출 할 수 있도록, 실제의 인스턴스 일 무슨 B2 컴파일 타임에 이야기하는 것은 불가능하다 일반 기지!). 그것은 예를 들어, lot 많은 혼란을 일으킬 수 있기 때문에 당신의 예제와 같은 경우 예외가 존재한다는 것은 실제로는 의미가 없으며, 이러한 경우는 그대로있는 그대로 제대로 작동하도록 쉽게 수정할 수 있습니다 (선언 된 유형 to Child not Base)를 선택합니다.

+4

난 상속의 요점은 당신이 "Base b1"을 선언하고 나중에 "b1.add"라고 말하면 Base.add 또는 Child.add를 실행하는지 여부가 객체의 런타임 유형에 따라 달라진다는 점입니다. . 그러나 Chris가 설명했듯이 선언 된 클래스에있는 함수 만 호출 할 수 있습니다. 컴파일러에서 확인할 수있는 것이 전부이기 때문입니다. – Jay

0

b1Base 형 변수이다. 이 클래스에는 subtract() 메서드가 없으므로 컴파일하는 데 실패했습니다.

+0

예, b1은 Base 유형이지만 Child 클래스를 가리 킵니까? – JavaUser

+1

그건 중요하지 않습니다. 이것은'Base' 타입이므로 컴파일러가 어떤 메소드를 사용할 수 있는지 결정하는 데 사용됩니다. 컴파일러는 주어진 시점에 어떤 유형을 가질지 알 수 없기 때문에 참조를 위해 변수 유형을 사용합니다. –

+0

xx..anyway 인스턴스는 하위입니다. Base 인스턴스에 Child 인스턴스를 참조하는 용도는 무엇입니까? – JavaUser

0

'원인 Base가 빼기가 없습니다.

b2와 b3은 하위로 정의되어 있기 때문에 빼기가 있습니다.

[편집 :] 아니요, b2는 빼기가 없습니다. 새 Child()로 정의되어 있어도 여전히 Base로 선언되어 있습니다.

1

코드가 컴파일되지 않기 때문에 JVM에서 아무 일도 발생하지 않습니다. Base에는 해당 구성원이 없기 때문에 b1.subtract() 메서드는 컴파일러에서 확인할 수 없습니다.

0

b1.subtract()에 대한 호출은 사용되는 클래스로 나눌 수 있습니다.

b1 ->Base

subtract() ->b1 이후 Child

Base, 아닌 Childb1subtract()라는 방법이 없기 때문에 b1.subtract()에 대한 호출이 작동하지 않을 것입니다.

0

BASE 클래스에 뺄셈 메서드가 없으므로 컴파일이 실패합니다. 그리고 b1은 base 유형입니다.

1

클래스가 컴파일되지 않습니다. 하위 클래스로 인스턴스화 된 기본 클래스 객체가 작동하는지 여부를 확인하려는 경우 대답은 '예'입니다.

Base b1 = new Base(); 
    Base b2 = new Child(); 

    Child b3 = new Child(); 

    b1.add(); 

    ((Child) b2).subtract(); // ?????????** 

    b2.add(); 
    b3.subtract(); 

다음과 같이 출력됩니다.

Base ADD 
Child Subtract 
Child ADD 
Child Subtract 

이것은 런타임 다형성이라고합니다.

0

subtract() 메소드는 Base 클래스 인터페이스의 일부가 아니며 실패한 이유입니다.

-1

Java는 엄격하게 정적으로 입력 된 언어입니다. 부모 클래스는 자식 클래스 메서드를 가리킬 수 없습니다. 컴파일시 Java 컴파일러는 클로저 원칙을 사용하여 Base 클래스에 subtract 메소드가 있는지 확인합니다.이 경우에는 빼기 메소드가 없으므로 컴파일 타임 오류가 발생합니다.