继承与多态动手动脑问题:
public class ParentChildTest {
public static void main(String[] args) {
Parent parent=new Parent();
parent.printValue();
Child child=new Child();
child.printValue();
parent=child;
parent.printValue();
parent.myValue++;
parent.printValue();
((Child)parent).myValue++;//基类对象赋给子类变量要执行强制类型转换
//语法:子类对象变量=(子类名)基类对象名;如果类型转换失败会抛出异常 parent.printValue();
}
}
class Parent{
public int myValue=100;
public void printValue() {
System.out.println("Parent.printValue(),myValue="+myValue);
}
}
class Child extends Parent{
public int myValue=200;
public void printValue() {
System.out.println("Child.printValue(),myValue="+myValue);
}
}
1.你的结果是:?
Parent.printValue(),myValue=100
Child.printValue(),myValue=200
Parent.printValue(),myValue=200
Child.printValue(),myValue=201
Child.printValue(),myValue==201
2.程序运行的结果是:
3.你如何解释会得到这样的输出?
第一行和第二行就是直接输出类中的数值,没有疑问。
而第三行输出的是200,原因是:
parent.myValue++相当于parent.myValue+parent.myValue即两次调用parent的方法,故输出应该是200
4.计算机是不会出错的,之所以得到这样的运行结果也是有原因的,那么从这些运行结果中,你能总结出Java的哪些语法特性?
当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。
这个特性实际上就是面向对象“多态”特性的具体表现。
如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。
如果子类被当作父类使用,则通过子类访问的字段是父类的!
思考:
为什么子类的构造方法在运行之前,必须调用父类的构造方法?能不能反过来?为什么不能反过来?
构造函数是一种特殊的方法,主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句。特别的一个类可以有多个构造函数,可根据其参数个数的不同或参数类型的不同来区分它们,即构造函数的重载。构造函数的主要功能用于在类的对象创建时定义初始化的状态。
构造一个对象,先调用其构造方法和成员变量。
子类拥有父的成员变量和成员方法,如果不调用,则从父类继承而来的成员变量和方法得不到正确的初始化。
不能反过来调用也是这个原因,因为父类根本不知道子类有什么变量而且这样一来子类也得不到初始化的父类变量,导致程序出错!
类型转换
下列语句哪一个将引起编译错误?为什么?哪一个会引起运行时错误?为什么? m=d; d=m; d=(Dog)m; d=c; c=(Cat)m; 先进行自我判断,得出结论后,运行TestCast.java实例代码,看看你的判断是否正确。
d=m,d=c运行时将会报错。因为m是父类对象,d是子类对象。将父类对象转化成子类对象,必须进行强制转换。而d和c是两个互不相干的类对象,所以不能将d赋值给c.