Ruijia 的个人资料学习用记事贴日志列表 工具 帮助
3月26日

迷思-Java Interface

  对于Java接口的使用出现在了一次的TP中。在这里撇开教科书中具体叙述的使用方法,语法结构不谈。对于接口使用的目的性,让我思索了一下。
  我们知道Java中,一个基类能被复数个派生类继承,但一个派生类只能继承一个基类。也就是说不能像C++那样实现多继承。这样自然可以避免掉多继承所带来的一些困扰,比如在派生类中产生多个基类的副本从而产生歧义性(通过虚继承可以解决),但是也丧失了多继承所带来的好处。试想一下,在Java中,我们现在要一个类有另一个类的属性,那么我们将通过继承来达到这个目的。但是,当我们很愉快地写这个派生类的时候,忽然发现这个派生类已经有了超类。这是一个很尴尬的局面,就好比你要给孩子找个爹,却尴尬地发现孩子他爹就在旁边。这个时候为了达到我们的原来目标,我们不得不,或者乐于使用接口弥补Java不能使用多继承的遗憾。从而不改变原来继承结构即孩子他爹还是原来那个孩子他爹,只是我们给孩子找了个老师来交他所需要的东西。这里就体现了Java接口的可插入性,我们可以让一个继承关系中的任意一个派生类实现某个接口,而不改变这个派生类的所有超类。并且我们愉快地知道一个类可以实现多个接口,如同实现了C++中的多继承而不用为歧义性多做困扰。因为接口中只有方法名,没有变量和完整定义。
  如果我快乐地接受上面的结论,那会是很白痴的一件事情。因为如果为了是某个类具有某项功能而又避免不能多继承的局限的话,我们完全可以用另一种方法来实现:
class a{
anotherclass1 b=new anotherclass1();
anotherclass2 c=new anotherclass2();
... ...
//这里我们可以实现无限多个类以便a的对象可以实现b,c....的功能
}
并不是说上述方法一定更好,只是这样当初接口的目的性就变得很荒谬了。所以,我想接口的使用实际上是对实现某一接口的那些类的统一管理归类。多数情况下,用户只需要知道有那些接口可供选择,而不想去关心到底这些接口是被那些类的对象所实现的。好比用户在取款机前提钱,只关心按什么钮可以拿到钱,不会去想究竟是取款机的哪一部分具体对按钮这个行为作出反映,他只要拿到钱就可以了。但多数情况下一个程序会支持有复数个运行环境,比如数据库使用Mysql或是Oracle,那么就会有不同的版本出现。但为了用户着想设计者还是友善地提供了统一的接口这样就不需要每个版本都出一本教材了。就像多数情况下使用者不知道究竟自己用的是Mysql还是Oracle,我们不清楚究竟自己使用的接口中的方法是被哪个类型具体实现的,不过那已经不是用户层的问题了,factory会友善地为我们选择实现哪个类型。
  就像上面说的那样,现在我们有了一些类实现了一个接口,我们就可以很方便的把这些类归于一类。并且用接口的名称来声明一个对象。比如:
public interface Collection{
  .... ...
}
public class Tableau implements Collection{
  ... ...
}
像这样一个接口被实现了,就可以如下声明:
Collection obj=new Collection();
如果Collection没有被实现这样做显然是错误的。这样我们得到了一个对象obj并且可以使用Collection中所有的已实现的方法。可是有的时候我们在类Tableau中加入了其他一些方法,如果用Collection声明对象后是不可以直接使用这些方法的,必须强制转换:((Tableau) obj).methode();既然Tableau是一个实现Collection的类,那么这样的强制转换自然是允许的。
  关于接口问题也许我的想法并不完全正确,或许是完全错误的。不过在今后的实际运用中会有更明确的答案。