实现类重用:继承和组合。
继承:优点:子类可以获得父类的属性和方法,如果访问权限允许子类可以直接访问父类的属性和方法----------------相当于子类直接复用父类的属性和方法。
缺点: 1.与父类严重耦合 ,2.破坏父类得封装性
1.封装:每个类都应该封装它的内部信息和实现细节,而只是暴漏必要的方法给其他类使用,但在继承关系中,子类可以直接访问父类的属性(内部信息)和方法,从而造成了子类和父类的严重耦合。
2.父类的实现细节对子类是透明的,子类可以访问父类的属性和方法,并可以改变父类方法的实现细节(方法重写的方式改变父类方法的实现),从而导致子类可以恶意篡改父类的方法。
为保证父类良好的封装性,不会被子类随意改变,设计父类遵循如下规则:
1.隐藏父类内部数据,属性设置成private访问类型。
2.不要让子类随意访问,修改父类的方法。private:子类无法访问 public:外部类调用,如果不希望被子类重写,可以再用final修饰。 protected:希望父类方法被子类重写,不希望其它类自由访问。
3.尽量不要再父类构造器中调用将要被子类重写的方法:
Class Base{
public Base(){
test()-------------------------------------------1
}
public void test(){
System.out.println(“将被子类重写的方法");
}
}
Class Sub extends Base{
Private String name="aaaaaaaaaaaaaa";
public void test(){------------------------------------------------------------------2
System.out.println("子类重写父类的方法,其name的字符串长度"+name.length());
}
public static void main(String[] args){
//下面代码会引起空指针错误
Sub su = new Sub();
}
}
错误分析:
当系统视图创建Sub对象时,同样先执行其父类的构造器,如果父类的构造器调用了被子类重写的方法,并不是调用1号test方法,而是调用2号test方法,此时Sub对象的name属性是null,因此会引发空指针异常。
继承关系的把握:什么时候需要从父类派生出子类
1.子类需要额外增加属性,而不仅仅是属性值的改变。
2.子类需要增加自己独有的行为方式。
如果是出于类复用的目的,并不一定需要使用继承,完全可以使用组合来实现。不管是继承还是组合,都可以在新类(对于继承就是子类)中直接复用旧类的public方法。
如果两个类之间有明确的整体,部分的关系,用组合关系来实现复用。
继承与组合的选择: 继承表达的是 is-a关系 组合表达的是:has-a关系