动手动脑-4
package 动手动脑; public class 基类 { public 基类() { System.out.println("基类 Created."); } public 基类(String string) { System.out.println("基类 Created.String:" + string); } } package 动手动脑; public class 父类 extends 基类 { public 父类() { super("Hello.Grandparent."); System.out.println("父类 Created"); //super("Hello.Grandparent."); } } package 动手动脑; public class 子类 extends 父类{ public 子类() { System.out.println("子类 Created"); } } package 动手动脑; public class 测试 { public static void main(String args[]) { 子类 c = new 子类(); } }
当super在父类构造函数上面时,最终的运行结果为:
基类 Created.String:Hello.Grandparent.
父类 Created
子类 Created
先调用基类有参构造函数,输出基类 Created.String:Hello.Grandparent.,然后再依次调用父类和子类构造函数。当super在父类构造函数的下面时,出现错误,程序无法运行。所以得出结论,用super调用基类的构造方法,必须是子类的第一个语句。
构造方法用于对基类的初始化。构造一个对象,先调用其构造方法,来初始化其成员函数和成员变量。子类拥有父的成员变量和成员方法,如果不调用,则从父类继承而来的成员变量和成员方法得不到正确的初始化。
package 动手动脑; public class 父类2 { public void sleeping() { System.out.println("父亲在睡觉。"); } } package 动手动脑; public class 子类2 extends 父类2{ public void sleeping() { super.sleeping(); System.out.println("孩子在睡觉。"); } } package 动手动脑; public class 测试2 { public static void main(String[] args) { 子类2 z=new 子类2(); z.sleeping(); } }
这个程序的运行结果为:
父亲在睡觉。
孩子在睡觉。
子类把父类的方法覆盖,通过super关键字来调用父类中的方法。
class Mammal{} class Dog extends Mammal {} class Cat extends Mammal{} public class TestCast { public static void main(String args[]) { Mammal m; Dog d=new Dog(); Cat c=new Cat(); m=d; //d=m; d=(Dog)m; //d=c; //c=(Cat)m; } }
通过运行我发现,当放开d=m这一行和d=c这一行的注释之后,编译出现错误,当放开c=(Cat)m这一行的注释之后,运行出现错误。因为m是父类创建的对象,而d是子类创建的对象,所以当d=m时需要进行类型强制转换,而没有转换会使编译出现错误。d=c这一行出现错误的原因是不能让同等地位的对象进行转换。
package 动手动脑; public class Child extends Parent { public int myValue=200; public void printValue() { System.out.println("Child.printValue(),myValue="+myValue); } } package 动手动脑; public class Parent { public int myValue=100; public void printValue() { System.out.println("Parent.printValue(),myValue="+myValue); } } package 动手动脑; public class ParentChildTest { public static void main(String[] args) { Parent parent=new Parent(); parent.printValue(); Child c=new Child(); c.printValue(); parent=c; parent.printValue(); parent.myValue++; parent.printValue(); ((Child)parent).myValue++; parent.printValue(); } }
这个程序运行之后的结果为:
Parent.printValue(),myValue=100
Child.printValue(),myValue=200
Child.printValue(),myValue=200
Child.printValue(),myValue=200
Child.printValue(),myValue=201
前两条结果不用解释,第三条,parent=c; 将子类变量赋给基类变量,这样就是体现了多态性,和Parent parent=new Child();的效果是一样的,此时当对象parent引用方法时,引用的是子类的方法,而当此对象引用变量时,引用的是父类的变量,所以在parent.printValue();时,输出的是子类中方法的输出语句,而parent.myValue++;时,增加的是父类变量myValue的值,而子类中myValue的值不变,所以当此对象再次引用此方法时,输出的仍是子类中此方法中的输出语句,而myValue的值不变,当使用了强制类型转换之后,((Child)parent).myValue++;此时(Child)parent就相当于是子类对象,引用变量myValue时,增加的是子类myValue的值,而调用方法之后,输出子类方法中的输出语句,而myValue得值发生变化。