这个其实就是一个向上转型的应用,这样的好处是既可以调用父类共有的特性,也可以调用子类更加强大的方法。 首先当执行这个语句的时候 SuperA t = new SubB(); //因为Sub是子类,super是父类,所以父类会先实例化,然后再实例化子类。A以为自己就是一个A,但是给他的却是个B。所以A不知道这些,他就以为他是自己,也就是A 所以调用的都是A自己有的方法和属性。但是事实上是残酷的,其实给他的实例是个B。当调用实例变量的时候,他会 调用他自己有的变量,(因为变量不能重写,A有变量的值,所以就会调用他自己的,即使你B里面没有也没关系,他只想调用 他自己的东西),当要调用方法的时候,发现自己的方法已经被覆盖了,所以只能调用子类的方法了。如果没有的话,还是会调用自己的方法的。 ******:我感觉关键点就是,属性不能覆盖这一点上面了!!!
new SubB时,内存中会分配空间,因为继承的关系,即有SuperA.a也有SubB.a。当调用t.a的时候,由于t这个引用声明的是SuperA类型,所以会对应的找SuperA.a,所以结果就是10。 但是方法就不一样了,方法是存在代码区的,并在程序运行期间动态加载,此时会判断 t 真正的类型(而不是引用的类型),类型为SubB,所以结果是调用SubB.test。
首先当执行这个语句的时候 SuperA t = new SubB();
//因为Sub是子类,super是父类,所以父类会先实例化,然后再实例化子类。A以为自己就是一个A,但是给他的却是个B。所以A不知道这些,他就以为他是自己,也就是A
所以调用的都是A自己有的方法和属性。但是事实上是残酷的,其实给他的实例是个B。当调用实例变量的时候,他会
调用他自己有的变量,(因为变量不能重写,A有变量的值,所以就会调用他自己的,即使你B里面没有也没关系,他只想调用
他自己的东西),当要调用方法的时候,发现自己的方法已经被覆盖了,所以只能调用子类的方法了。如果没有的话,还是会调用自己的方法的。
******:我感觉关键点就是,属性不能覆盖这一点上面了!!!
但是方法就不一样了,方法是存在代码区的,并在程序运行期间动态加载,此时会判断 t 真正的类型(而不是引用的类型),类型为SubB,所以结果是调用SubB.test。