继承和多态是JAVA开发语言的三大特性中的两个。今天在看设计模式的书时,由于对两个概念掌握得不是很好,导致花费了半天的时间来重新学习。
现在我们先说继承的概念:java语言使用extends关键字实现子类继承父类,派生出新的类,子类继承父类的所有非私有(private)的成员变量和方法,通俗的说法就是子类拥有父类的行为。用一个例子说明:
父类Father.java:
public class Father {
public int i = 0;
public Collection<?> doSomething(Map<?, ?> map){
System.out.println("父类被执行");
return map.values();
}
public void doSomething(){
System.out.println("调用父类方法");
}
}
子类Son.java:
public class Son extends Father{
}
doSomething。用下面的代码可以得到验证:
public class Clint {
public static void invoker(){
Son s = new Son();
System.out.println(s.i);
}
public static void main(String args[]){
invoker();
}
}
执行的结果为:0。
如果子类中成员变量名称和父类相同时,则子类覆盖父类的变量,这时子类不再继承父类这个相同的成员变量,对Son类做如下的修改,Clint类不变,则执行的结果为2:
public class Son extends Father{
public int i = 2;
}
子类的某个方法时,先在自己的成员方法中查找,如果找到,则执行,否则在父类中查找,如果有则执行,没有则查找父类的父类,依次类推。我们在此对Son进行修改,验证上面的说法。
public class Son extends Father{
public int i = 2;
public Collection<?> doSomething(Map<?, ?> map){
System.out.println("子类被执行");
return map.values();
}
}
Clint类:
public class Clint {
public static void invoker(){
Son s = new Son();
Map map = new HashMap();
s.doSomething(map);
}
public static void main(String args[]){
invoker();
}
}
类被执行
把子类的的doSomething方法注释掉,则执行的结果为:父类被执行。
子类的静态方法不能重写父类的非静态方法。子类的非静态方法不能重写父类的静态方法。
讲完继承,现在开始讲多态。多态是指某个接口(或者父类)的某个方法被多个子类实现(或重写)时,会产生不同的动作行为,而我们在写代码时只需把子类的实例指向接口(或父类)的引用,就可以执行真正子类中的方法。Father f = new Son()。这个例子就是多态的写法,编译时是按照Father实例来处理,运行时是则按照Son实例来处理。
我们还是用上面的例子来验证:
public class Father {
public int i = 0;
public static Collection<?> doSomething( HashMap<?, ?> map){
System.out.println("父类被执行");
return map.values();
}
public void doSomething(){
System.out.println("调用父类方法");
}
}
public class Son extends Father{
public int i = 2;
public Collection<?> doSomething(HashMap<?, ?> map){
System.out.println("子类被执行");
return map.values();
}
}
public class Clint {
public static void invoker(){
Father s = new Son();
HashMap map = new HashMap();
s.doSomething(map);
}
public static void main(String args[]){
invoker();
}
}
子类被执行。说明我们在执行Father s = new Son();这样代码时,s引用实际上指向的是Son实例。
在使用多态时要注意,父类只能访问子类中继承或重写了父类的方法,而不能访问子类自己的方法。
我们把Father做一些修改,把doSomething方法中的HashMap改为Map。大家猜猜执行的结果是什么呢?我问过好多有5年工作经验的程序员,他们都回答错了。实际的执行结果是“父类被执行”。为什么会是这个结果呢?因为子类中的doSomething方法不是继承于父类,也不是重写父类的doSomething方法,而是自己的一个方法,而Father s = new Son()这行代码执行时,s指向的是Son对象,但是它又是Father的引用,只能访问Son类中重写doSomething的方法,如果没有重写doSomething的方法,则执行Father类的doSomething方法,因此最终的执行结果是“父类被执行”。