继承
。继承能够实现类的复用
。类封装将内部信息和实现细节隐藏。而继承使得子类能够从父类得到成员变量和方法。当拥有访问权限情况下,子类可以直接访问父类中的成员变量和方法。因此继承破坏了类的封装
。为保证父类良好的封装性,设计父类时遵循原则:
。。尽量隐藏父类的内部数据(private)
。。不要让子类可以随意访问、修改父类方法:
*父类中那些仅为辅助其他的工具方法,应该使用private修饰
*若父类中的方法需要被外部的类调用,则必须以public修饰,但又不希望被子类重写该方法,可使用final修饰方法
*若希望父类的某个方法被子类重写,但又不希望其他类访问,将该方法访问权限设置为protected
。。尽量不要在父类构造器中调用要被子类重写的方法(引发空指针异常)
*举个例子
1 package test; 2 3 class Base{ 4 5 public Base() 6 { 7 test(); 8 } 9 10 public void test() 11 { 12 System.out.println("将被子类重写的方法"); 13 } 14 } 15 public class Sub extends Base{ 16 17 private String name; 18 19 public void test() 20 { 21 System.out.println("子类重写父类的方法,"+"name.length="+name.length()); 22 } 23 24 25 public static void main(String[] args) { 26 27 Sub sub=new Sub();
29 } 30 31 32 }
*结果
*分析
**在创建Sub对象时,系统会先执行父类构造器,父类构造器调用test()方法,而test方法在子类当中得到重写,则调用的是子类当中的test方法,而test方法中的name实例变量为null,引发空指针
。父类需要派生子类时,要求子类是特殊的子类
。。子类需要额外增加的属性,而不仅仅是属性值的改变
。。子类需要添加特有的行为方法
利用组合实现复用
1.继承实现类的复用
。关系图
。实例
1 package test; 2 3 class Animal{ 4 5 private void beat() 6 { 7 System.out.println("beating"); 8 } 9 10 public void breath() 11 { 12 beat(); 13 System.out.println("breathing"); 14 } 15 } 16 17 class Bir extends Animal{ 18 19 public void fly() 20 { 21 System.out.println("flying"); 22 } 23 24 } 25 26 class Wolf extends Animal{ 27 28 public void run() 29 { 30 System.out.println("running"); 31 } 32 } 33 34 public class InheritTest { 35 public static void main(String[] args) { 36 Bir bird=new Bir(); 37 bird.breath(); 38 bird.fly(); 39 Wolf wolf=new Wolf(); 40 wolf.breath(); 41 wolf.run(); 42 } 43 44 }
。结果
。通过继承复用父类中的breath方法
。。对于继承而言,子类直接获得父类中的public方法,程序使用子类时可以直接访问从父类继承得到的方法
2.组合实现类的复用
。关系图
。实例
1 package test; 2 3 class Animal{ 4 5 private void beat() 6 { 7 System.out.println("beating"); 8 } 9 10 public void breath() 11 { 12 beat(); 13 System.out.println("breathing"); 14 } 15 } 16 17 class Bird{ 18 private Animal animal;//将Animal类组合到Bird类中,作为其一部分 19 20 public Bird(Animal animal) 21 { 22 this.animal=animal; 23 } 24 //重新定义一个breath方法 25 public void breath() 26 { 27 animal.breath();//直接复用Animal提供的breath()方法实现Bird中的breath()方法 28 } 29 30 public void fly() 31 { 32 System.out.println("flying"); 33 } 34 } 35 36 class Wolf{ 37 38 private Animal animal; 39 40 public Wolf(Animal animal) 41 { 42 this.animal=animal; 43 } 44 45 public void breath() 46 { 47 animal.breath(); 48 } 49 50 public void run() 51 { 52 System.out.println("running"); 53 } 54 } 55 56 public class CompositeTest { 57 58 public static void main(String[] args) { 59 //需要显示创建被组合对象 60 Animal animal=new Animal(); 61 Bird bird=new Bird(animal); 62 bird.breath(); 63 bird.fly(); 64 65 Animal animal1=new Animal(); 66 Wolf wolf=new Wolf(animal1); 67 wolf.breath(); 68 wolf.run(); 69 } 70 71 }
。结果
。通过组合复用Animal中的breath方法
。。组合将旧类作为新类的成员变量组合进来,用以实现信了你的功能,用户看到的是新类的方法,而不能看到被组合对象的方法,因此通常需要在新类里使用private修饰被组合的旧类对象
3.继承和组合的选择
。依据现实需求选择到底是继承还是组合。
。。如以上例子中,Animal和Bird、Wolf间通过继承实现更具有现实意义
。。继承表达“is-a”关系
。。组合表达“has-a”关系,包含整体与部分的关系