• Java用个继承咋就这么难


    试想一个问题:

    如果我们需要给一个超类的方法实现一种更强的功能,也就是加强版的超类,一般会怎么做?

    继承?

    Too young too simple!

    看看下面的例子:

    当我们需要一个类,需要HashSet类的所有方法,但是随时需要知道在其创建到目前,已经加入过多少元素,该如何实现?

    一般使用继承,覆盖add()和addAll()方法,会显得很合理:

     1 public class InstrumentedHashSet<E> extends HashSet<E>{
     2     private int mCount;
     3     
     4     public int getmCount() {
     5         return mCount;
     6     }
     7     @Override
     8     public boolean add(E e) {
     9         mCount ++;
    10         return super.add(e);
    11     }
    12     @Override
    13     public boolean addAll(Collection<? extends E> e) {
    14         mCount += e.size();
    15         return super.addAll(e);
    16     }
    17 }

    第9行和第14行进行了对mCount的增加,那么真的像我们想象的那样吗?

     1     public static void main(String[] args) {
     2         InstrumentedHashSet<String> mHashSet = new InstrumentedHashSet<String>();
     3         
     4         ArrayList<String> mArrayList = new ArrayList<String>();
     5         mArrayList.add("1");
     6         mArrayList.add("2");
     7         mArrayList.add("3");
     8     
     9         mHashSet.addAll(mArrayList);
    10         System.out.println("总共插入了" + mHashSet.getmCount());
    11         
    12     }

     最后输出: 总共插入了9 

    Why?

    其实是因为,在HashSet内部的实现中,addAll()方法是调用了add()方法的,这一点虽然坑爹,但是没有必要在文档中说明。在这个类中,只要我们去掉add()的覆盖,就可以良好的运行程序。

    那么,问题来了,以后遇到这种需求的时候,还要不要用继承呢?

    可能你认为这是个例,注意点就行了,那么,当你想要使用继承的时候,回答以下几个问题:

    1.如果这样的父类在以后的版本中有改变呢?

    2.如果父类加入了新的方法而自己却没有实现呢?

    更甚至,你可能认为我使用继承,但是不覆盖原有方法就安全了?考虑以下几个问题:

    1.如果超类添加了一个方法,而你给子类提供的方法的函数签名碰巧与它相同,但是返回结果不同。那么,编译器不会通过这个方法。

    2.如果函数签名和返回类型都相同,那不又是继承了吗?

    幸运的是,有一种办法可以解决以上问题,那就是看起来不起眼的 ——组合(复合)!

    这样,原有的类就成了新类的一个组件,新类中的每个示例方法都可以调用被包含现有类示例中的对应方法,并返回它的结果,这被称为“转发”,新类中的方法被称为转发方法

    这样的类非常稳固,即使向现有的类增加了新的方法,也不会影响新的类。

    只有当子类是真正的超类的子类型的时候,才可以使用继承,也就是说,必须存在“is-a”关系时候才适合使用继承。

    -----------------------------------------------------

    Github:

    https://github.com/RainFool
  • 相关阅读:
    iOS使用自签名证书实现HTTPS请求
    DB操作-用批处理执行Sql语句
    SSL通信-忽略证书认证错误
    oracle 19c awr 丢失 i/o信息
    this.$route.query刷新后类型改变
    wx.navigateTo在app.js中偶发性失效
    微信小程序new Date()转换日期格式时iphonex为NaN
    下载cnpm成功,cnpm -v却不识别
    element-ui的表单验证如何清除校验提示语
    5. 最长回文子串(动态规划算法)
  • 原文地址:https://www.cnblogs.com/RainFool/p/4252030.html
Copyright © 2020-2023  润新知