为了账号安全,请及时绑定邮箱和手机立即绑定

多态对象特性

当创建一个父类的引用指向本类的对象时,如何使用这个对象调取本类的特性?例如:

父类:Traveltool;本类:Taxi;他们的特性:int site;如何调用对象obj3来调用Taxi里面的site值?

Traveltool obj3 = new Taxi();

System.out.println(obj3.site);

这个命令输出的是Traveltool中的site值。为什么obj3是Taxi的对象,却调用了父类的特性?

正在回答

5 回答

由于你声明成员变量是都是public,导致Taxi类中实际上存在两个site,两个way变量,当对象为Traveltool时条用的则是父类的site(没有初值默认为零),就是你的这种情况。想要输出5则要创建一个子类的对象,如Taxi taxi = (Taxi)obj;System.out.println(taxi.site);结果就是5.

0 回复 有任何疑惑可以回复我~
#1

Levin2016 提问者

谢谢你的回答。但是,如果这个是这样,那么是不是site里也有两个canDo()方法呢?而当我用obj调用canDo()方法的时候,输出的却是Taxi的canDo()方法,即Taxi can travel fast on road!为什么不是调用父类的方法呢?
2016-07-24 回复 有任何疑惑可以回复我~
#2

Smile丶微冷 回复 Levin2016 提问者

方法和变量不同,由于是继承关系子类已经将原本父类中的canDo方法覆盖,也就是创建的对象中只有一个canDo函数,由于是通过new Taxi创建,自然调用的是子类的canDo方法
2016-07-24 回复 有任何疑惑可以回复我~
#3

Levin2016 提问者 回复 Smile丶微冷

谢谢,我还是没理解透彻。语句:Traveltool obj = new Taxi(); ,实际创建的是Traveltool的对象还是Taxi的对象呢? 如果是Traveltool的对象,为什么调用的是Taxi的方法? 如果是Taxi的对象,为什么调用的是Traveltool的变量值呢?
2016-07-24 回复 有任何疑惑可以回复我~
#4

Smile丶微冷 回复 Levin2016 提问者

实际创建的永远是new后的类型,new类型时系统是按照Taxi开辟了一块内存,由于Traveltool是它的父类所以可以引用这块内存,即Traveltool obj = new Taxi();但实际的内存空间还是Taxi类型。当调用变量时,系统会根据当前的类型就近匹配变量,也就是Traveltool 使用Traveltool 的变量,Taxi使用Taxi的变量。当调用方法时,由于Taxi重写了Traveltool 的方法,在Taxi只存在一个canDo方法,所以不论用Traveltool 还是Taxi类型的变量去调用canDo方法,调用的都是Taxi重写过后的方法。
2016-07-24 回复 有任何疑惑可以回复我~
#5

Smile丶微冷 回复 Levin2016 提问者

切记不可以把成员变量的方法的调用过程混淆,父类子类声明相同的公共变量时是共存的,而方法的重写意义相当于覆盖,不能同时存在。
2016-07-24 回复 有任何疑惑可以回复我~
#6

Levin2016 提问者

非常感谢你的耐心解答!
2016-07-25 回复 有任何疑惑可以回复我~
#7

Levin2016 提问者 回复 Smile丶微冷

多谢大神耐心解答!我还有一个疑问,就是如果我用Traveltool obj = new Taxi();创建了对象,我是不是就无法调用taxi的site了?也就是说,我如果想调用子类的成员变量的时候,就不能用继承的方法创建子类的对象呢?
2016-07-25 回复 有任何疑惑可以回复我~
#8

Smile丶微冷 回复 Levin2016 提问者

当调用Taxi中的site时可以先将Traveltool obj强制转换成Taxi类型Taxi obj2 = (Taxi)obj;不过出于封装的考虑,一般情况下是不会将类中的成员变量设置为public,而是通过适当的方法来调用,当子类想要调用父类变量或者方法时使用super,输出本身的变量时则用this,这样就既可以得到父类的变量又可以输出自己的变量。不过子类如果拥有与父类同名的变量时,表示子类的新特性,一般情况不会再去调用父类的同名变量。
2016-07-25 回复 有任何疑惑可以回复我~
查看5条回复

这个通过存储地址很好解释,比如创建一个类A占用1.0M内存,类B继承类A ,创建类B 则占用1.5M内存(即类B内存大小0.5M),当我们new B();时,编译器为我们分配1.5M内存,分别为(A+B),当我们对象类型是类A时,类A对象就只指向1.0M内存中的数据,所以输出0,当我们调用方法时,因为B继承A,并且B类重写了A的方法,所以我们看到是调用B中的方法。当然,对象类型为B时,对象指向1.5M的内存,我们输出 site的值也就是B中的数值!(注:个人理解)

0 回复 有任何疑惑可以回复我~

谢谢,我还是没理解透彻。语句:Traveltool obj = new Taxi(); ,实际创建的是Traveltool的对象还是Taxi的对象呢?

如果是Traveltool的对象,为什么调用的是Taxi的方法?

如果是Taxi的对象,为什么调用的是Traveltool的变量值呢?

0 回复 有任何疑惑可以回复我~

package com.imooc;

//父类

public class Traveltool {

public String way = "Traveltoll can travel!" ;

public int site;

public void canDo(){

System.out.println("Traveltool can travel fast on road! " + "Bike can take " + site + " people!");

}

}

package com.imooc;

//子类

public class Taxi extends Traveltool {

String way = "Taxi travel by road";

int site = 5;

public void canDo(){

System.out.println("Taxi can travel fast on road! " + "Bike can take " + site + " people!");

}

}

package com.imooc;

//初始化类

public class Initial {

public static void main(String[] args) {

// TODO Auto-generated method stub

Traveltool obj = new Taxi();

System.out.println(obj.site);

}

}

结果为什么是0而不是5?

0 回复 有任何疑惑可以回复我~

(我不太清楚你的意思,你是指父类和子类都定义了site这个数据吗?额,还有,site这个数据你不封装起来吗?或者是site是一个方法?)根据多态性,编译器在编译的时会通过动态绑定生成一个方法表,如果方法中,有同样的签名,会自动调用一个最合适的方法。

0 回复 有任何疑惑可以回复我~
#1

Levin2016 提问者

public class Traveltool {//父类 public int site; public class Taxi extends Traveltool {//子类 String way = "Taxi travel by road"; int site = 5; public class Initial {//初始化类 public static void main(String[] args) { System.out.println(obj.site); //为什么结果是0而不是5?
2016-07-23 回复 有任何疑惑可以回复我~
#2

Levin2016 提问者

public class Initial { public static void main(String[] args) { Traveltool obj = new Taxi(); System.out.println(obj.site); 为什么结果是0而不是5?因为我创建的是子类的对象,为什么不调用子类的site值呢
2016-07-23 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消
Java入门第二季 升级版
  • 参与学习       530631    人
  • 解答问题       6091    个

课程升级!以终为始告别枯燥,在开发和重构中体会Java面向对象编程的奥妙

进入课程

多态对象特性

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信