使用继承一方面可以复用代码,公共的属性和行为可以 放到父类当中,而子类只需要关心子类的特有的性质就行可以了;另一方面,不同的子类的对象可以更为方便地被统一处理。
- 在java中,即使没有声明父类,也会有一个隐藏的父类Object,即任何类都可以调用Object类的方法。
- 一个类最多只有一个父类,使用extends关键字来表示继承
- 子类不能直接访问父类中的私有属性或者方法,即用private关键字修饰的属性或者方法,此外protected的属性或者方法可以被继承,也可以直接访问
public class A { private int i; private static void write() { System.out.println("write....A"); } protected void fun() { System.out.println("hello !!!!!!!!!!"); } }
public class B extends A { @Override protected void fun() { // TODO Auto-generated method stub super.fun(); } private static void write() { System.out.println("write >>>>B"); } public static void main(String[] args) throws InterruptedException { B b = new B(); b.fun(); b.write();; } }
运行结果:
-
hello !!!!!!!!!! write >>>>B
如上所示,通过创建B的对象变量b;调用write()方法实质上是调用的子类的write() ,与父类无关。
- 子类变量和方法与父类的有重名情况下,可通过使用super强行调用父类的变量或者方法
- 另外,在new的过程中父类的构造方法也会执行,并先于子类的构造方法执行。可通过super关键字来调用相应的构造器,没有的情况下调用的是默认的父类构造器。
- 继承也是有风险的,在子类可能会破坏父类的封装性。封装是为了隐藏类内部的实现细节,提供简化接口,使用者只需要关注怎么用而不需要关注内不怎么实现。但是子类与父类之间可以存在着实现细节的依赖,在继承父类之后子类不得不需要去关心父类怎么实现的细节,而父类修改其内部的实现时也要考虑到对子类的影响。如下代码:
-
public class Base { private static final int MAX_NUM = 1000; private int [] arr = new int[MAX_NUM]; private int count; public void add(int number) { if(count < MAX_NUM) { arr[count++] = number; } } public void addAll(int []numbers) { for(int num : numbers ) { add(num); } } }
public class Child extends Base { private long sum; @Override public void add(int number) { // TODO Auto-generated method stub super.add(number); sum +=number; } @Override public void addAll(int[] numbers) { // TODO Auto-generated method stub super.addAll(numbers); for(int i=0 ; i<numbers.length ; i++) { sum +=numbers[i]; } } public long getSum() { return sum; } public static void main(String[] args) { Child child = new Child(); child.addAll(new int[]{1,2,3,4}); System.out.println(child.getSum()); } }
子类中重写了Base类的add()与addAll()方法,再添加数字的同时把数字存放到数组中,存储数字的和到实例变量sum中,并提供getSum()获取sum的值。
-
使用addAll()方法添加{1,2,3,4},期望输出是1+2+3+4=10,但是实际输出为20.原因是数字被添加了俩回,子类需要知道基类的实现细节,才能可能避免地程序的错误实现。
- 避免父类的方法不可随意修改的问题,可通过给方法加final关键字,父类可保留对该方法的内部实现自由,但是该方法就不可被重写。
- 此外使用组合可以抵挡父类变化对子类的影响,从而保护子类;还有就是可以使用接口的办法。