java多态中,父类不能引用子类的属性

class Person{
String name = "person";
}

class Son extends Person {
String name = "son";
}

public class Test {
public static void main(String[] args){
Person p = new Son();
System.out.println(p.name);
}
}
结果为person。
为什么不是son?

因为Person p = new Son();

就是把子类转型为父类

子类转型为父类的规则:

    只能调用父类的属性

    只能调用父类未被复写的方法

    只能调用被子类复写的方法

----------------------------------------------------------------------------------------------------------------

而属性并不能被复写,只是重名了。对此我们可以验证一下:

在父类添加一个fun(){System.out.println("父类方法");}

在子类复写方法fun(){System.out.println("子类方法");}

然后在主方法中:

Son p2 = new Son();

p2.run();                        //子类直接调用fun方法

((Person )p2).run();     //转成父类后调用fun方法

System.out.println(p2.name);                    //子类直接调用name属性    

System.out.println(((Person )p2).name);  //转成父类后调用name属性    

结果输出是:

子类方法        

子类方法         <-------由于方法被子类覆盖了所以即使转型成父类也同样是调用被复写的方法

son

person           <-------虽然属性被重名了,但并不能覆盖掉父类的属性!!

通俗的说就是:父类中的name属性属于父类的,子类的name属性属于子类的。

所以子类转型为父类后调用的name是父类中name属性,且也只能调用父类的属性。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2013-07-05
父类和子类的关系很微妙,有这样一种情况。当子类拥有继承的父类同名的属性和方法时,它就会把父类的同名和方法给“屏蔽了”,父类的方法和属性不起作用;否则就会拥有父类方法。还有就是重写只限于同名(应该是同方法名,同参数列表和返回值)的方法,子类同名的属性不会重写父类,除非是通过通名方法调用。
第2个回答  2013-07-05
变量是静态绑定,方法是动态绑定。静态绑定就是变量本身什么类型,就用哪个里面的。例如,你的p.name的p是Person类型,那么name就是Person类中的name。而如果是动态绑定,那么会从本身类型开始向超类型查找。如果name是方法,那么用于p是Son类的一个对象,所以会从Son开始找name方法,如果找不到再到父类中找。追问

javac命令 生成.class文件这个过程是不是可以理解成编译,static变量,static块等在这个过程中被初始化,前期绑定发生在这个阶段;java命令这个过程是不是理解成执行,后期绑定发生在这过程?

追答

可以这么理解!

追问

p.name-静态绑定,p的地址来自于哪里?是来自于son构造器对person构造器的调用吗?p的地址跟p是怎么弄建立映射的?

追答

p指向的是Son对象,因为你创建的是Son。但是,引用是用类型的,你的p被定义为了Person,那么p.name访问的就是Person里的变量,如果你Son p = new Son();那么p.name就是Son里的变量。

本回答被提问者采纳
第3个回答  2018-08-21
多态:
package com.se.duotai;
/**
* 最近对多态有点乱 希望高人指点
这里的针对3次输出结果分别展开
1.第一次输出的时候 很简单 子类调用自己的成员 无疑问
2.第二次输出时 因为子类做了个类型提升 成为了父类类型 此时可以访问到父类中的变量故此时输出的x是5。
3.第三次输出 创建了父类对象 访问父类成员
问题:2.3结果综合来看 为什么第二次输出的时候变量是父类的5,而方法却是调用了子类覆盖后的方法。
将对象类型提升与第三种方式有什么区别。在内存中重载是个什么过程。
*
*/
class Fu // 父类
{
int x = 5;
public void show() {
System.out.println("父");
}
public void showParent() {
System.out.println("父 类未被重写的方法");
}
}
class Zi extends Fu// 子类
{
int x = 7;
public void show() {
System.out.println("子");
}
}
public class Test{
public static void main(String[] args) {
Zi z = new Zi(); // 创建子类类型的对象
z.show(); // 调用子类对象方法
//Sop(z.x); // 输出x
System.out.println(z.x);
Fu f = z; // z对象提升为父类类型
f.show(); // 调用show方法(只能调用被子类复写的方法)
f.showParent();
//Sop(f.x); // 输出x
System.out.println(f.x);
Fu k = new Fu(); // 创建父类对象
k.show(); // 调用父类show方法
//Sop(k.x); // 输出父类x
System.out.println(k.x);
}
}
/**
* 因为Person p = new Son();
就是把子类转型为父类
子类转型为父类的规则:
只能调用父类的属性
只能调用父类未被复写的方法
只能调用被子类复写的方法
*/
第4个回答  2013-07-05
因为你的类型就是Person,而且实例化Son的构造器也是继承父类的
相似回答