子类覆盖父类的方法与属性后,把子类强制转化为父类类型,为什么这时方法体是子类的,而属性却是父类的呢?
子类覆盖父类的方法与属性后,把子类强制转化为父类类型,为什么这时方法体是子类的,而属性却是父类的呢?
有如下代码可证(呵呵,透露一下,是IBM的面试题,至今我还未解开这个迷,请高手多多指教,不才感激不尽!):
- Java code
public class FatherClild { public static void main(String[] are) { Child c = new Child(); Parent p = c; System.out.println(p.ParentVar); System.out.println(p.ParentStaticVar); System.out.println(p.ParentStaticStr); System.out.println(c.ParentVar); System.out.println(c.ParentStaticVar); System.out.println(c.ParentStaticStr); p.parentMethod(); p.parentStaticMethod(); c.parentMethod(); c.parentStaticMethod(); }}class Child extends Parent { public int ParentVar = 15; public static int ParentStaticVar = 14; //public static String ParentStaticStr = "child"; static { System.out.println("this is a Child static block"); } public Child() { System.out.println("this is a Child construct"); } public void parentMethod() { System.out.println("this is a Child method"); } public int getParentStaticVar() { return super.ParentVar; } public static void parentStaticMethod() { System.out.println("this is a Child static method"); }}/* * */class Parent { public int ParentVar = 5; public static int ParentStaticVar = 4; public static String ParentStaticStr = "parent"; static { System.out.println("this is a parent static block"); } public Parent() { System.out.println("this is a parent construct"); } public void parentMethod() { System.out.println("this is a parent method"); } public static void parentStaticMethod() { System.out.println("this is a parent static method"); }}打印的结果是:
this is a parent static block
this is a Child static block
this is a parent construct
this is a Child construct
5
4
parent
15
14
parent
this is a Child method
this is a parent static method
this is a Child method
this is a Child static method
通过学习,把我对这些了解的与大家共享一下,望能有更多的交流
1)类被自动执行的顺序
静态域(类被加载时)
静态初始化块(类加载时,当然这时的静态域要先有值,才便于正确执行)
非静态域(实例开辟内存时)
非静态初始化块(实例开辟内存时)
构造方法(实例生成对象引用时)
2)当实例化一个第3代的类时,发生的动作将是这样的
加载第3代,但第3代来源于第2代
所以加载第2代,但第2代来源于第1代
所以加载第1代。
所以:
(1)第1代类被加载,发生第1代类加载时的动作(即,静态初始化块)
(2)第2代类被加载,发生第2代类加载时的动作
(3)第3代类被加载,发生第3代类加载时的动作
加载完之后,开始创建第3代,但第3代来源于第2代
所以创建第2代,但第2代来源于第1代
所以创建第1代
所以
(4)第1代被创建,并初始化,完成该时期的动作(即,非静态初始化块,接着 构造方法)
(5)第2代被创建,并初始化,完成该时期的动作
(6)第3代被创建,并初始化,完成该时期的动作
继承父类的理解[]
从个人理解上看:
创建父类对象的证据是:子类里都有一个super,它就是父类对象,可见,要创建子类,一定会先创建父类,只是父类做为子类的一个属性(可以这么理解)所以整体上看,是只创建了一个子类。
简明地说:
设计者让子类的初始化是首先用父的构造方法来展开的,所以子类在完成造构之前(刚完成调用父类的构造方法展开)父类就实例化了。
所以我理解了,为什么有的程序只是创建一个对象,却执行了满世界的代码了
还有一重大发现:
当父类有多个造构方法时,在子类的构造方法里,可以决定自己是用父类的那个构造方法生成的,所以super()只能用一次,且必须放在构造方法的第一句。
可见,java在代码复用上下的功夫真不少:
1)父类的代码可以供所有的子类使用
2)子类在继承父类时,可以选择不同的父类构造方法,得到功能不同的子类(注,只是选择了一个方法,就能达到功能不同,可见代码重用性又提高了)
注:创建子类时,都会调用父类的构造方法来初始化,系统默认调用无参的父类构造方法。
若子类的构造方法里,没有指明用父类的构造方法来初始化,则系统自动添加父类的无参构造方法,
要是此时,父类没有无参的构造方法时,这些将出现编译报错了。(呵呵,编译器还是满厉害的)
默认情况下,所有的类都有无参构造方法,但自定了构造方法后,系统自带的无参构造方法将不存在,除非再自定义一个无参构造方法
呵呵,似乎话多了!这是我平常记录的。
对我提的问题,我还有一个思路:
变量的值取决于我们定义的变量的类型,而不是创建的对象的类型,这与编译器是在什么时候(编译、运行)进行匹配的有关系?为什么要分不同的时期匹配?
[解决办法]
子类覆盖父类的方法与属性后,把子类强制转化为父类类型,为什么这时方法体是子类的,而属性却是父类的呢?
我就来说说这句。。
关于多态的问题,我一直以现实生活中的例子来理解。比如交通工具是父类,自行车和小汽车都是继承他的子类,我新建一个自行车的交通工具,他的行驶方式肯定是脚踏,而不是开动发动机。同理,对于新建一个小汽车的交通工具,他的行驶方式 肯定是开动发动机而不是脚踏。而由于他们都是继承自交通工具,他们肯定拥有交通工具应该具有的一些属性,比如有轮子,能行驶,需要掌握方向等。在此基础上,子类可以扩展自己拥有的属性。。
[解决办法]
override仅仅是说对父类方法的重新定义,与属性无关.
而且override机制对父类的static/private和final方法无关
父类的属性只能够隐藏.
[解决办法]
方法产生多态,而属性不产生多态
[解决办法]
父亲有钱先养活了多个孩子,父亲老了没能力赚钱了,只能靠孩子养活了。
今天感恩节,节日快乐。
[解决办法]
"创建父类对象的证据是:子类里都有一个super,它就是父类对象,可见,要创建子类,一定会先创建父类,只是父类做为子类的一个属性(可以这么理解)所以整体上看,是只创建了一个子类。 "
调用父类的构造方法,初始化子类从父类继承下来的成员变量
[解决办法]
多态只对方法,属性不产生多态。
[解决办法]
属性只能被隐藏而不能被覆盖,静态的属性和方法属于类而不是对象
[解决办法]
结果应该是这样的吧
this is a parent static block
this is a Child static block
this is a parent construct
this is a Child construct
5
4
parent
15
14
child
this is a Child method
this is a parent static method
this is a Child method
this is a Child static method
[解决办法]
方法是动态绑定的,属性不是喵~~``
[解决办法]
这样说吧,多态,只有方法才有多态一说,属性是没有这个说法的.
多态必须满足的条件是:继承,方法的覆盖,以及父类引用指向子类对象.这时候调用的方式是子类的,当然,前提是非static和非private方法.
属性只有隐藏一说,不可能满足多态的条件.父类的引用,它的类型还是父类的类型,调用的属性还是父类的属性.