继承和组合的概念
在新类里简单地创建原有类的对象我们把这种方法叫作组合因为新类由现有类的对象合并而成我们只是简单地重复利用代码的功能而不是采用它的形式
第二种方法是创建一个新类将其作为现有类的一个类型我们可以原样采取现有类的形式并在其中加入新代码同时不会对现有的类产生影响这种魔术般的行为叫作继承(Inheritance)涉及的大多数工作都是由编译器完成的对于面向对象的程序设计继承是最重要的基础概念之一对于组合和继承这两种方法大多数语法和行为都是类似的(因为它们都要根据现有的类型生成新类型)
组合也就是一个类的对象是另外一个类的成员一般的程序都有组合的意味只不过是基本数据类型是成员变量下面请看具体的例子
class Head
{
Head(){
Systemoutprintln( head );
}
}
class Body
{
Body(){
Systemoutprintln( 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=;
public Person(String nint a)
{
name=n;
age=a;
}
int getAge()
{
return age;
}
String getName()
{
return name;
}
void getDescription()
{
Systemoutprintln(name: +name+\t+age: +age);
}
}
class Student extends Person
{
private String studno=null;
public Student(String nString noint a)
{
super(na);
studno=no;
}
}
说明:Student类中有三个成员变量nameagestudno和一个方法getDescription();
注意:子类继承了父类的所有变量和函数只是子类不能访问父类的private类型的变量和函数其实privae类型的变量还是继承到子类中的
无论还是继承都允许我们将子对象置于自己的新类中大家或许会奇怪两者间的差异以及到底该如何选择
如果想利用新类内部一个现有类的特性而不想使用它的接口通常应选择组合也就是说我们可嵌入一个对象使自己能用它实现新类的特性但新类的用户会看到我们已定义的接口而不是来自嵌入对象的接口考虑到这种效果我们需在新类里嵌入现有类的private对象
有些时候我们想让类用户直接访问新类的组合也就是说需要将成员对象的属性变为public成员对象会将自身隐藏起来所以这是一种安全的做法而且在用户知道我们准备合成一系列组件时接口就更容易理解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[];
public Door left = new Door()
right = new Door(); // door
Car() {
for(int i = ; i < ; i++)
wheel[i] = new Wheel();
}
public static void main(String[] args) {
Car car = new Car();
carleftwindowrollup();
carwheel[]inflate();
}
} ///:~
由于汽车的装配是故障分析时需要考虑的一项因素(并非只是基础设计简单的一部分)所以有助于客户程序员理解如何使用类而且类创建者的编程复杂程度也会大幅度降低
如选择继承就需要取得一个现成的类并制作它的一个特殊版本通常这意味着我们准备使用一个常规用途的类并根据特定的需求对其进行定制只需稍加想象就知道自己不能用一个车辆对象来组合一辆汽车——汽车并不包含车辆相反它属于车辆的一种类别属于关系是用继承来表达的而包含关系是用组合来表达的
protected
现在我们已理解了继承的概念protected这个关键字最后终于有了意义在理想情况下private成员随时都是私有的任何人不得访问但在实际应用中经常想把某些东西深深地藏起来但同时允许访问衍生类的成员protected关键字可帮助我们做到这一点它的意思是它本身是私有的但可由从这个类继承的任何东西或者同一个包内的其他任何东西访问也就是说Java中的protected会成为进入友好状态
我们采取的最好的做法是保持成员的private状态——无论如何都应保留对基 础的实施细节进行修改的权利在这一前提下可通过protected方法允许类的继承者进行受到控制的访问
import javautil*;
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的过程中得到了大量的强调但并不意味着应该尽可能地到处使用它相反使用它时要特别慎重只有在清楚知道继承在所有方法中最有效的前提下才可考虑它为判断自己到底应该选用组合还是继承一个最简单的办法就是考虑是否需要从新类上溯造型回基础类若必须上溯就需要继承但如果不需要上溯造型就应提醒自己防止继承的滥用但只要记住经常问自己