search

Home  >  Q&A  >  body text

java继承中,为什么向上转型后无法运行子类中特有的方法?

看了这篇文章:
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方法,然后执行。
实际情况大家都知道有错误,编译不通过。
这中间肯定漏了点我不知道的什么?希望可以赐教。
换个方式问也就是:
当发生向上转型的时候,栈和堆中分别发生了什么?

怪我咯怪我咯2767 days ago480

reply all(4)I'll reply

  • PHPz

    PHPz2017-04-17 17:21:39

    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

    reply
    0
  • 黄舟

    黄舟2017-04-17 17:21:39

    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:

    Person girl = new Girl();
    girl.speak(); 

    The declaration type of girl is Person, and Person does not have the speak 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 your girl executes. girl的声明类型是Person,而Person并没有speak这个方法,所以会报错。注意是编译器报的编译期的错误,编译器是不管你那个girl执行的类型到底是什么。

    运行期,虚拟机当然会知道girl执行的堆中对象是Girl类型。

    编译器为什么要根据变量的声明类型来决定能不能调用某个方法?其中一个原因就是,编译期间可能根本不知道这个变量在运行期绑定的到底是什么类型的对象。举个例子:

    Person p = Math. random() > 0.5 ? new Girl() : Boy();

    这个例子中的p

    During runtime, the virtual machine will of course know that the object in the heap executed by girl is of type Girl. 🎜 🎜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. 🎜

    reply
    0
  • ringa_lee

    ringa_lee2017-04-17 17:21:39

    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 and Boy defined by the subject are used. When PersonGirlBoy。当

    Person ps = new Girl(); 

    定义一个对象ps以后,它在编译时的类型是Person,而实际运行时的类型是Girl

    在使用ps这个对象时,程序只知道它是个Person,而一个Person只有eatspeak两个方法,所以在调用对象成员的时候只能调用eatspeak两个方法;程序并不知道ps对象的实际类型是Girl,所以不能调用Girl独有的sing方法。即:

    ps.eat();    // OK,调用父类实现
    ps.speak();  // OK,调用子类实现
    ps.sing();   // Error

    那么,既然程序并不知道ps对象的实际动态类型是Girl,为什么ps.speak();还能调用Girl rrreee After defining an object ps, its type at compile time is Person, but its actual runtime type is Girl.

    When using the ps object, the program only knows that it is a Person, and a Person only has eat and < There are two methods code>speak, so when calling object members, only two methods eat and speak can be called; the program does not know ps The actual type of the object is Girl, so the unique sing method of Girl cannot be called. That is:

    rrreee

    So, since the program does not know that the actual dynamic type of the ps object is Girl, why can ps.speak(); still call Girl? This is what

    polymorphism

    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. 🎜

    reply
    0
  • 大家讲道理

    大家讲道理2017-04-17 17:21:39

    The Stack is person, the heap is girl, and the person class has no reference to the sing method.

    reply
    0
  • Cancelreply