作为一种面向对象的编程语言,java的一大特色就是丰富和完备的继承机制,这里的继承既包括子类对父类的继承,也包括各种类对于接口的实现。
继承的特点就是子类能够继承父类的所有属性和方法,并且子类可以添加自己的属性和方法,从这种意义上说,子类就是特殊的父类。这极大的提升了程序的可复用性,只要设计好父类,之后添加子类时就可以节省下大量的代码,通过重载和重写,子类的设计也有很大得灵活性,来看下面这个例子。
//父类构造器
public CommonPlanningEntry(String name,Location A, Location B,
String time1,String time2) {
this.name=name;
Aa=A;
Bb=B;
Locations.add(Aa);
Locations.add(Bb);
begin=new Timeslot(time1);
Timeslots.add(new PairTimeslot(time1,time2));
end=new Timeslot(time2);
}
//父类方法
public void allocateresource(Resource H) {
state=new ALLOCATED();
Resources.add(H);
}
//子类构造器
public CourseEntry(String name, Location A, String time1, String time2) {
....
}
//子类方法
@Override
public void allocateresource(Resource H)
{
super.allocateresource(H);
if(teacher==null)
{
teacher=(Teacher)H;
}
}
上面这段代码子类的方法重写了父类的方法,子类的构造器重载了父类的方法。重载和重写得区别在这里不再细说,只需要明白重写是修改了父类的方法,本质上是一个方法,而重载是借助父类方法的壳产生了新的方法,原来的方法仍然存在,本质上是两个方法。
然而,即便拥有重载和重写,万能的继承也有它触及不到的地方。事实上在许多问题中,子问题和父问题是有很大差异的,也就是说父类的许多属性和方法子类根本就不需要。也许有人会问难道这样就不能使用继承了吗,继承之后只使用子类需要的方法,子类不需要的方法直接利用重写设置空实现禁用岂不美哉。但我们之前说过,子类是特殊的父类,特殊的父类也是父类,你现在连父类的方法都没有了还能称作父类吗,用java中的标准术语来说就是违背LSP原则。
于是,真正万能的委托就在此时登场了。其实,即使不知道什么是委托的java萌新在一开始使用java时肯定早就使用过委托了。稍微复杂点的程序,在设计时肯定设计了不止一个类,一个类的实现依赖于其他类(且不是继承),这就是委托。来看下面这个例子。
public class CommonPlanningEntry<R> {
private EntryState state=new WAITING();
private Timeslot begin;
private Timeslot end;
public int getTimecount() {
return begin.getTimecount();
}
可以看到,其实CommonPlanningEntry和Timeslot根本就不是什么父类子类关系,也一点也不相像。这时候用继承肯定不合适,但CommonPlanningEntry又需要用到Timeslot的方法,这时候就将Timeslot嵌入到 CommonPlanningEntry中,将需要用到的方法委托给Timeslot执行。有时候继承和委托同时使用的,比如说很类似的两个类之间,即使大部分方法都相同,但有那么少数几个方法不需要,这时候先继承后再委托就完美地解决了问题,比如说java的Decorator模式。
interface Stack
{
void push(Item e);
Item pop();
}
public abstract class StackDecorator implements Stack
{
protected final Stack stack;
public StackDecorator(Stack stack)
{
this.stack = stack;
}
public void push(Item e)
{
stack.push(e);
}
public Item pop()
{
return stack.pop();
} ...
}
public class UndoStack extends StackDecorator
{
private final UndoLog log = new UndoLog();
public UndoStack(Stack stack) { super(stack); }
public void push(Item e)
{
super.push(e);
log.append(UndoLog.PUSH, e);
}
public void undo()
{
//implement decorator behaviors on stack
} ...
}
通过这样的模式可以实现各个类特性的任意组合。