java继承和多态的理解

继承和多态是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{
}

上述的代码中子类Son拥有父类Father的成员变量i和成员方法 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;
}

如果子类的成员方法和父类的成员方法一样(这里说的一样是指方法名、方法参数类型和方法参数数量以及抛出的类型完全一致。),则称为子类重写(override)父类的方法。可以在之类中使用super关键字访问父类中被子类重写的方法。执行 子类的某个方法时,先在自己的成员方法中查找,如果找到,则执行,否则在父类中查找,如果有则执行,没有则查找父类的父类,依次类推。我们在此对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方法,因此最终的执行结果是“父类被执行”。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值