继承的双面性

继承作为java的三大特性之一,功能很强大,继承了父类的子类,就拥有了父类的全部特性(除final修饰的方法,变量以外),子类可以通过重写父类的方法,达到更具体的实现,更灵活的扩展。
但是继承也有双面性。有两个缺点:
1.破坏封装
子类在继承父类的方法并且实现时,需要不得不关注父类中对该方法的实现,看一下有没有破坏原有的结构。而父类在更改自身方法时也需要考虑子类,如果不考虑,也可能会影响到子类的实现。举个例子:

//父类
public class Student {

      private static final int MAX=10;
      private int [] arr=new int [MAX];
      private int  count;

      public void add (int num){
          System.out.println("父类add");
          if(count<MAX){
              arr[count++]=num;
          }
      }
      public void addAll(int [] nums){
          System.out.println("父类addAll");
          for (int i =0;i<nums.length;i++){
              add(nums[i]);
          }
      }

}

//子类
public class TestClass extends Student {

  private long sum;
    //添加求和功能
    @Override
    public void add (int num){
        System.out.println("子类add");
       super.add(num);
//       sum+=num;
    }
    @Override
    public void addAll(int [] nums){
        System.out.println("子类addAll");
        super.addAll(nums);
        for (int i =0;i<nums.length;i++){
          sum+=nums[i];
        }
    }
    public long getSum(){
        return sum;
    }
//执行
 public static void main(String[] args) {
        TestClass testClass=new TestClass();
        testClass.addAll(new  int[]{1,2,3});
        System.out.println(testClass.getSum());
    }

期望为6,实际却为12, 我们只希望他在子类的addall 进行一个数字汇总,殊不知addall方法在父类中调用了add方法,而重写了add方法会优先调用子类的add方法,而子类的add方法同样进行了数据的汇总,所以进行了两次汇总,结果不尽人意。

此时我们删掉子类中的两个方法中任意一个汇总的代码即可。

如果子类不知道基类方法的实现细节,它就不能正确的进行扩展。对于子类而言,通过继承实现,是没有安全保障的,父类修改内部实现细节,它的功能就可能会被破坏,而对于基类而言,让子类继承和重写方法,就可能丧失随意修改内部实现的自由。

继承没有反映"is-a"关系
什么是is-a关系,is-a表名子类是父类的一种,父类的属性和行为也一定适用于子类。就像橙子和水果一样,水果有的属性橙子必须要有。
在“is-a”关系中,重写方法时,子类不应该改变父类预期的行为,但是这又是没办法约束的。
继承应该是被当做“is-a”来使用的,但java没有办法约束,父类的属性和行为,子类不一定都适用,子类甚至还可以重写和预期完全不一样的行为。如果是用父类引用操作子类对象时,会把其当做父类对象使用,但其方法实现的效果如果又和预期不一样,这样会造成混乱。

如何避免继承的双面性
1.父类不希望被继承的属性方法用final 修饰
2.不继承,将需要的对象以属性的方式写入类中
3.使用接口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值