2017-10-20 2 views
1

동적 바인딩이 런타임에 발생하는 동안 정적 바인딩이 컴파일 타임에 발생한다는 사실을 알고 있습니다. 나는 몇 가지 관련 질문을 읽었습니다. Java 동적 바인딩 및 메서드 재정의 프로세스

class Cake { 
    public void taste (Cake c) { 
     System.out.println("In taste of Cake class"); 
    } 
} 

class ChocolateCake extends Cake { 
    public void taste(Cake c) { 
     System.out.println("In taste (Cake version) of ChocolateCake class"); 
    } 
    public void taste(ChocolateCake cc) { 
     System.out.println("In taste (ChocolateCake version) of ChocolateCake class"); 
    } 
} 

class BirthdayCake extends ChocolateCake { 
    public void taste(Cake c) { 
     System.out.println("In taste (Cake version) of BirthdayCake class"); 
    } 
    public void taste (ChocolateCake cc) { 
     System.out.println("In taste (ChocolateCake version) of BirthdayCake class"); 
    } 
    public void taste(BirthdayCake bc) { 
     System.out.println("In taste (BirthdayCake version) of BirthdayCake class"); 
    } 
} 

다음 개체

가 작성되었습니다 :

Cake c1 = new Cake(); 
ChocolateCake cc = new ChocolateCake(); 
Cake c2 = new ChocolateCake(); 
Cake c3 = new BirthdayCake(); 
는 아래와 같이 특정 질문을 나에게 오는 다시 때 나는 그들 중 많은 사람들의 생각의 기차를 따라 수 있지만, 나는 엉망 내 논리를 잃었다

출력은 다음과 같습니다 :

기본적으로
c1.taste(cc);//Output: In taste of Cake class 
cc.taste(cc);//Output: In taste (ChocolateCake version) of ChocolateCake class 
c2.taste(cc);//Output: In taste (Cake version) of ChocolateCake class 
((BirthdayCake) c3).taste(cc);//Output: In taste (ChocolateCake version) of BirthdayCake class 
((BirthdayCake) c3).taste((BirthdayCake) c3);//Output: In taste (BirthdayCake version) of BirthdayCake class 

c2.taste(cc) 클래스 ChocolateCaketaste(Cake c) 메소드를 호출하는 이유, 내 질문은? c2의 정적 유형은 Cake의 메소드를 호출 할거야 것을 결정 Cake입니다 :

여기에 내 생각이다. 실행 시간이되면 동적 유형 인 c2 즉 ChocolateCake을 사용하여 ChocolateCake 케이크를 호출하는 방법을 결정합니다. 매개 변수의 유형이 ChocolateCake이며, 결국은 taste(ChocolateCake cc)으로 결정됩니다.

분명히이 생각은 잘못되었습니다. 정적 유형 c2Cake이고 클래스 Cake에 하나의 메서드 만 있기 때문에 메서드의 서명이 컴파일 타임에 완료되었다고 가정합니다. 런타임에 관해서는 클래스 에있는 override 메소드를 호출합니다. 모든 것이 의미가 있습니다. 내 혼란은 왜 그것이 이전 방식이 아닌 방식으로 작동한다는 것인가?

ChocolateCake cc = new Cake(); :

내가 이해하지 못하는 또 다른 것은 우리가 컴파일 오류가 발생하는 것처럼 다음과 같은 명령문을 작성하는 것을 허용하지 않는 것입니다.

그러나 ChocolateCake 타입 참조가 결국 ChocolateCaketaste(Cake c) 메소드를 호출하여 위와 같이 올바른 결과를 얻으므로 Cake 객체를 전달할 수있는 이유는 무엇입니까?

개체 참조에 대한 메서드 호출의 전체 프로세스를 아직 이해하지 못한다고 생각합니다. 컴파일 타임에 가장 잘 맞는 메소드를 결정할 때 일어나는 일과 그 이후에 일어나는 일과 마찬가지로 실행 시간 (이 과정에서 다른 단계가 있는지 확신 할 수 없음)을 가정 해 봅시다.

누구든지이 프로세스를 설명 할 수 있습니까? 감사합니다.

+1

매개 변수 바인딩이 동적이 아닌 문제가 있습니다. 이 매개 변수는 컴파일 타임에'Cake.cake (Cake c) '에 바인딩 되었기 때문에 런타임에 여전히'Cake'가 될 것이지만, 동적 인 메소드 호출은 결국'ChocolateCake.cake (Cake c)'가 될 것입니다. . 아마이 질문에 대한 좋은 사본이 있습니다. 제가 찾을 수 있는지 보도록하겠습니다. – Kayaman

+0

고마움, 당신의 대답은 내 질문에 거의 해결. 그러나 나는 지난 몇 부분에서 언급 한 것처럼 매개 변수를 전달하는 것과 여전히 혼동 스럽습니다. 즉,'ChocolateCake cc = new Cake(); '와 같은 문이 허용되지 않는 동안'ChocolateCake' 유형 참조가 마지막으로'Cake' 객체를 전달할 수있는 이유는 무엇입니까? –

+1

그건 단지 기본적인 유산 일뿐입니다. 모든 케이크는 '케이크'이지만 '케이크'는 '초콜릿 케이크'가 아닙니다. 'Woman w = new Human(); '이라고 쓰지는 않을 것입니다. 왜냐하면 그것은 반드시 사실 일 필요가 없기 때문입니다. – Kayaman

답변

0

예제를 간소화하고 단계를 진행해 보겠습니다. 또한 명확성을 위해 @Override를 추가했습니다. 당신이 cake.taste(param);를 호출 할 때

class Cake { 
    public void taste (Cake c) { 
     System.out.println("In taste of Cake class"); 
    } 
} 

class ChocolateCake extends Cake { 
    @Override 
    public void taste(Cake c) { 
     System.out.println("In taste (Cake version) of ChocolateCake class"); 
    } 
    public void taste(ChocolateCake cc) { 
     System.out.println("In taste (ChocolateCake version) of ChocolateCake class"); 
    } 
} 

ChocolateCake param = new ChocolateCake();  
Cake cake = new ChocolateCake(); 
cake.taste(param); 

는 자바 컴파일러가 아닌 실제 객체 참조가 가리키는 입력 방법을 참조의 유형에 따라, callled됩니다 컴파일 시간을 선택합니다.

cake의 참조 타입 Cake이므로 컴파일러 taste 호출과 매개 변수로서 수용된다 Cake 방법의 기본 클래스 Cake에 보인다.ChocolateCakeCake이므로 (상속을 통해) 컴파일러는 일치하는 항목을 찾습니다. 본질적 런타임 동안 의한 동적 디스패치베이스 taste 방법의 대체를 갖기 때문에

는 JVM은 ChocolateType하고 이미 선택 방법의 대체를 호출 cake 기준의 실제 유형을 해결한다.