慢慢来吧,实在是说来话长。设计师都是面向接口编程的。接口是面向对象编程的精华所在。不是可有可无的。 看看这个 List l = new Vector(); List l = new ArrayList(); 当系统的实现需要改变的时候,从Vector变到ArrayList只需修改这一句话,而客户端的所有所有其他的代码都是List这个接口提供的,对吧?所以才有这种灵活性。
你错误地理解了效率问题就你说的多重继承,举个例子来讲,java在n多年的时间里没有模板范型,但是依然活得很好,因为所有东西都是Object, 能够放进Collection里(虽然拿出来稍微麻烦一点),而C++却不行。同样,接口的这边,方便的地方不是implement的那些class,而是使用这些class的地方, 比如for (Iterator it = instruments.iterator(); it.hasNext(); ) { Instrument ins = (Instrument) it.next(); //这里只需要转型成接口(父)类型而不是具体的某个乐器。因为我们接下来对ins的操作都是在Instrument接口里面已经定义了的,它们各自的新功能我们不关心。 ins.play(); }
楼上的都说得很清楚了。List l = new Vector(); 然后客户开始使用l。这里客户并不关心我使用的是Vector还是ArrayList,只关心我在使用List的接口。事实上,如果看不到上一句,客户端也不可能知道他使用的到底是什么。 for(Iterator iter=l.terator; l.hasNext():){ System.out.println(iter.next()); }等等吧。但是,突然有一天,你发现Vector影响了效率,你把它改成了ArrayList,List l = new ArrayList(); 这就是说,你只给了用户List接口,所以你给自己留下了后路。现在客户端的代码一句都不用改变,对吧。这就是我所说的那些了。 当系统的实现需要改变的时候,从Vector变到ArrayList只需修改这一句话
比如你定义一个Chicken的接口, 你不希望用户自己new鸡,哪只把接口暴露给用户就好了.
那你直接说一下,Bruce Eckel 写上 "implement Comparator" 目的是我问题中所说的:“为了UML 更清晰,好让客户端程序员知道:“哦,这个类实现了Comparator,于是我可以知道里面有一个 compare()可以调用”吗?也就是你说的所谓协议,这对于设计一个大型应用是很有帮助的。是不是这样子?
差不多,应该这样想:这个类实现了Comparator接口,那么这个类就是一个Comparator,那么这个类可以用在任何一个需要Comparator的地方。
那么别的类和这个类之间打交道时只需要知道和其打交道的是一个Comparator,而不需知道他具体是AlphabeticComparator 还是NumberComparator 等等。这样就封装了具体实现。可以方便地动态切换他是用哪个具体实现。这是通过多态实现的。
比如for (Iterator it = instruments.iterator(); it.hasNext(); ) {
Instrument ins = (Instrument) it.next(); //这里只需要转型成接口(父)类型而不是具体的某个乐器。因为我们接下来对ins的操作都是在Instrument接口里面已经定义了的,它们各自的新功能我们不关心。
ins.play();
}
然后客户开始使用l。这里客户并不关心我使用的是Vector还是ArrayList,只关心我在使用List的接口。事实上,如果看不到上一句,客户端也不可能知道他使用的到底是什么。
for(Iterator iter=l.terator; l.hasNext():){
System.out.println(iter.next());
}等等吧。但是,突然有一天,你发现Vector影响了效率,你把它改成了ArrayList,List l = new ArrayList();
这就是说,你只给了用户List接口,所以你给自己留下了后路。现在客户端的代码一句都不用改变,对吧。这就是我所说的那些了。
当系统的实现需要改变的时候,从Vector变到ArrayList只需修改这一句话