看了这篇文章:
https://www.ibm.com/developerworks/cn/java/j-lo-polymorph/
有一些疑问。
class Person {
public String toString(){
return "I'm a person.";
}
public void eat(){}
public void speak(){}
}
class Boy extends Person{
public String toString(){
return "I'm a boy";
}
public void speak(){}
public void fight(){}
}
class Girl extends Person{
public String toString(){
return "I'm a girl";
}
public void speak(){}
public void sing(){}
}
//最后这么用的话,
Person girl = new Girl();
girl.speak();
按照作者的说法,girl引用变量指向堆中的 Girl对象,所以运行的时候知道当前对象是Girl对象,找Girl的方法表,
找到后执行。这对于speak方法来说是行得通的。
但是如果这样呢:
girl.sing();
按照作者的说法,去Girl方法表找到sing方法,然后执行。
实际情况大家都知道有错误,编译不通过。
这中间肯定漏了点我不知道的什么?希望可以赐教。
换个方式问也就是:
当发生向上转型的时候,栈和堆中分别发生了什么?
The source code is like this, there are still some omitted things, please post the complete code. According to your code now, you didn’t
Person girl = new Girl()
girl .speak()
These two sentences should be placed in main. You call them directly in the class. The structure is wrong
It's the variable's declared type that determines which methods it can call, not the actual type of the object in the heap it points to.
Like you:
The declaration type of
girl
isPerson
, andPerson
does not have thespeak
method, so an error will be reported. Note that this is a compile-time error reported by the compiler. The compiler does not care what type yourgirl
executes.girl
的声明类型是Person
,而Person
并没有speak
这个方法,所以会报错。注意是编译器报的编译期的错误,编译器是不管你那个girl
执行的类型到底是什么。运行期,虚拟机当然会知道
girl
执行的堆中对象是Girl
类型。编译器为什么要根据变量的声明类型来决定能不能调用某个方法?其中一个原因就是,编译期间可能根本不知道这个变量在运行期绑定的到底是什么类型的对象。举个例子:
这个例子中的
During runtime, the virtual machine will of course know that the object in the heap executed byp
girl
is of typeGirl
. 🎜 🎜Why does the compiler decide whether a method can be called based on the declared type of the variable? One of the reasons is that during compilation, it may not be known at all what type of object this variable is bound to at runtime. For example: 🎜 rrreee 🎜p
in this example cannot determine the true type of the object it is bound to until runtime. 🎜The subject’s question involves the concept of polymorphism. Let’s use the example of the subject to illustrate:
Assume that the three classes
Person
,Girl
andBoy
defined by the subject are used. WhenPerson
、Girl
和Boy
。当定义一个对象
ps
以后,它在编译时的类型是Person
,而实际运行时的类型是Girl
。在使用
ps
这个对象时,程序只知道它是个Person
,而一个Person
只有eat
和speak
两个方法,所以在调用对象成员的时候只能调用eat
和speak
两个方法;程序并不知道ps
对象的实际类型是Girl
,所以不能调用Girl
独有的sing
方法。即:那么,既然程序并不知道
When using theps
对象的实际动态类型是Girl
,为什么ps.speak();
还能调用Girl
rrreee After defining an objectps
, its type at compile time isPerson
, but its actual runtime type isGirl
.ps
object, the program only knows that it is aPerson
, and aPerson
only haseat
and speak, so when calling object members, only two methodseat
andspeak
can be called; the program does not knowps
The actual type of the object isGirl
, so the uniquesing
method ofGirl
cannot be called. That is:rrreee
So, since the program does not know that the actual dynamic type of theps
object isGirl
, why canps.speak();
still callGirl
? This is whatpolymorphism
looks like. 🎜 🎜For a parent class pointer/reference pointing to a subclass, if the parent class method is overridden in the subclass, then when this method is called through the parent class pointer/reference, the compiler will compile the parent class's Method calls are dynamically bound to methods of the actual type. Those methods that have not been overridden by subclasses will be statically bound to the methods of the parent class. 🎜 🎜This is understood from an abstract perspective. The lower-level implementation method must refer to the specific implementation, which is explained more clearly in the article provided by the subject. 🎜The Stack is person, the heap is girl, and the person class has no reference to the sing method.