面向对象8——继承和组合

继承

。继承能够实现类的复用

。类封装将内部信息和实现细节隐藏。而继承使得子类能够从父类得到成员变量和方法。当拥有访问权限情况下,子类可以直接访问父类中的成员变量和方法。因此继承破坏了类的封装

。为保证父类良好的封装性,设计父类时遵循原则:

  。。尽量隐藏父类的内部数据(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”关系,包含整体与部分的关系

猜你喜欢

转载自www.cnblogs.com/Demetris/p/9234617.html