组合和继承

组合,有的书里面也叫聚合。由现有的类生成新的类,有两种方法就是组合与继承。我们把UML中的关联关系和聚集关系统称为组合关系。组合与继承都是提高代码可重用性的手段。在设计对象模型时,可以按照语义来识别类之间的组合关系和继承关系。在有些情况下,采用组合关系或者继承关系能完成同样的任务,组合和继承存在着对应关系:组合中的整体类和继承中的子类对应,组合中的局部类和继承中的父类对应。

       组合是将现有的类型作为新类底层实现的一部分来加以复用通常就是一个类里用另一类当他的数据成员。与继承有什么区别?起初我都觉得区别这两个概念比较幼稚,想当然这两者是泾渭分明,不存在象抽象与接口之间如此难分清红皂白,纠葛不清。组合是象是说“我请了个老头在我家里干活”,只讲究没有情感的has 。继承是说“我父亲在家里给我帮了很大的忙”是对一个类的兼收并蓄。 组合一般是将现有的类型作为新类型底层实现的一部分来加以复用,在一个类中引用另一个类。而继承是拥有了父类的非私有方法。其中“is-a (是一个)”的关系是用继承来表达的,而“has-a(有一个)”的关系则是用组合来表达的。但后来想想如果让一个JAVA程序员辩认是组合,还是继承,当然没有太多的意义,问题是在抽象问题的阶段,你自己如何去准确把握什么时候用组合,什么时候用继承。

       组合关系和继承关系相比,前者的最主要优势是不会破坏封装,在软件开发阶段,组合关系虽然不会比继承关系减少编码量,但是到了软件维护阶段,由于组合关系使系统具有较好的松耦合性,因此使得系统更加容易维护。组合关系的缺点是比继承关系要创建更多的对象。从软件构架来说,组合,耦合度比继承弱,继承是对父类方法和数据成员的兼收并蓄,而组合,可以有选择得使用某一种方法。

       只有明确维持着“是一个”关系时,才使用继承,否则组合才是最好的选择。为判断自己到底应该选用组合还是继承,一个最简单的办法就是考虑是否需要从新类上溯造型回基础类。若必须上溯,就需要继承。但如果不需要上溯造型,就应提醒自己防止继承的滥用。但只要记住经常问自己“我真的需要上溯造型吗”,对于组合还是继承的选择就不应该是个太大的问题。组合这种重用方式只是很单纯的重复运用以有的代码功能,而非重复运用其形式。继承让新的class成为既有class的一类,并且根据需要加入新的功能,而无须更动原有class。从设计模式上看来!java只支持单继承。如果你想同时继承两个类是绝对做不到的。另外。如果继承泛滥。或让一个class里面的内容变得非常的臃肿。有的方法其实并不是我们需要关注的方法。他也会继承下来! 如果用组合就不一样了。能把已有的两个类,引用进来,可以使用我们自己比较感兴趣的方法!所以说能用组合尽量用组合。打个比方,Vehicle类是所有车辆的类,它至少具有可被驾驶的功能;而Car是所有小娇车的类,它具有了载人的功能,它必须回溯,因为它必须具有被驾驶的功能。而Car上的方向盘与刹车,与Car之间只是简单地使用了它们具有的功能,是整体与部分的关系。所以是组合使用的。

   在新类里简单地创建原有类的对象。我们把这种方法叫作“组合”,因为新类由现有类的对象合并而成。我们只是简单地重复利用代码的功能。

     第二种方法是创建一个新类,将其作为现有类的一个“类型”。我们可以原样采取现有类的形式,并在其中加入新代码,同时不会对现有的类产生影响。这种魔术般的行为叫作“继承”(Inheritance),涉及的大多数工作都是由编译器完成的。对于面向对象的程序设计,“继承”是最重要的基础概念之一。

     对于组合和继承这两种方法,大多数语法和行为都是类似的(因为它们都要根据现有的类型生成新类型)。

     组合也就是一个类的对象是另外一个类的成员,一般的程序都有组合的意味,只不过是基本数据类型是成员变量,下面请看具体的例子

class Head
{
       Head(){
      System.out.println(" head ");
      }
}

class Body
{
      Body(){
      System.out.println(" body ");
      }
}

class Person()
{
      Head h=null;
      Body b=null;

Person() //人是由头和身体组成的,Head和Body的对象是Person的一部分
    { 
      h=new Head();
      b =new Body();
    }

}

继承作为面向对象的三个重要特性的一个方面,在面向对象的领域有着及其重要的作用,好像没听说哪个面向对象的语言不支持继承
class Person 

private String name=null;
private int age=0;
public Person(String n,int a)
{
name=n;
age=a; 
}
int getAge()

return age;
}
String getName()

return name;
}
void getDescription()

System.out.println("name: "+name+"/t"+"age: "+age);
}
}

class Student extends Person

private String studno=null;
public Student(String n,String no,int a)

super(n,a);
studno=no;
}
}

说明:Student类中有三个成员变量name,age,studno和一个方法getDescription();
注意:子类继承了父类的所有变量和函数,子类不能访问父类的private类型的变量和函数. 

无论组合还是继承,都允许我们将子对象置于自己的新类中。大家或许会奇怪两者间的差异,以及到底该如何选择。
  car(汽车)对象便是一个很好的例子:

class Engine { 
public void start() {} 
public void rev() {} 
public void stop() {}
}

class Wheel { 
   public void inflate(int psi) {}
}

class Window { 
   public void rollup() {} 
   public void rolldown() {}
}

class Door { 
   public Window window = new Window(); 
   public void open() {}
    public void close() {}
}

   public class Car { 
    public Engine engine = new Engine(); 
    public Wheel[] wheel = new Wheel[4]; 
    public Door left = new Door(), right = new Door();

    // 2-door
      Car() {
       for(int i = 0; i < 4; i++) 
         wheel[i] = new Wheel(); 
      } 
      public static void main(String[] args) { 
       Car car = new Car(); 
       car.left.window.rollup(); 
       car.wheel[0].inflate(72); 
    }
} ///:~

    由于汽车的装配是故障分析时需要考虑的一项因素(并非只是基础设计简单的一部分),所以有助于客户程序员理解如何使用类,而且类创建者的编程复杂程度也会大幅度降低。如选择继承,就需要取得一个现成的类,并制作它的一个特殊版本。通常,这意味着我们准备使用一个常规用途的类,并根据特定的需求对其进行定制。只需稍加想象,就知道自己不能用一个车辆对象来组合一辆汽车
——汽车并不“包含”车辆;相反,它“属于”车辆的一种类别。“属于”关系是用继承来表达的,而“包含”关系是用组合来表达的。

protected
    现在我们已理解了继承的概念,protected这个关键字最后终于有了意义。在理想情况下,private成员随时都是“私有”的,任何人不得访问。但在实际应用中,经常想把某些东西深深地藏起来,但同时允许访问衍生类的成员。protected关键字可帮助我们做到这一点。它的意思是“它本身是私有的,但可由从这个类继承的任何东西或者同一个包内的其他任何东西访问”。也就是说,Java中的protected会成为进入“友好”状态。

     我们采取的最好的做法是保持成员的private状态——无论如何都应保留对基础的实施细节进行修改的权利。在这一前提下,可通过protected方法允许类的继承者进行受到控制的访问:

import java.util.*;
class Villain { 
private int i; 
protected int read() { return i; } 

   protected void set(int ii) { i = ii; } 
public Villain(int ii) { i = ii; } 
   public int value(int m) { 
      return m*i; 
   }
}

   public class Orc extends Villain {
    private int j; 
      public Orc(int jj) { 
          super(jj); 
          j = jj; 
      } 

     public void change(int x) { 
       set(x);
     }
} ///:~

可以看到,change()拥有对set()的访问权限,因为它的属性是protected(受到保护的)。

再论合成与继承

    在面向对象的程序设计中,创建和使用代码最可能采取的一种做法是:将数据和方法统一封装到一个类里,并且使用那个类的对象。有些时候,需通过“组合”技术用现成的类来构造新类。而继承是最少见的一种做法。因此,尽管继承在学习OOP的过程中得到了大量的强调,但并不意味着应该尽可能地到处使用它。相反,使用它时要特别慎重。只有在清楚知道继承在所有方法中最有效的前提下,才可考虑它。

       为判断自己到底应该选用组合还是继承,一个最简单的办法就是考虑是否需要从新类上溯造型回基础类。若必须上溯,就需要继承。但如果不需要上溯造型,就应提醒自己防止继承的滥用。但只要记住经常问自己“我真的需要上溯造型吗”,对于组合还是继承的选择就不应该是个太大的问题.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值