在大家看到我的这篇文章时,我正在拜读刘未鹏先生写的《暗时间》,如果你有幸看到我的这篇博客,我希望你也可以看看这本书。好了闲话少叙,进入正题。
在面向对象的Collection中处处体现泛型和多态的思想,且慢,由于泛型和多态两者之间本身就有一定的相似性,让我们先认清楚泛型和多态之后再进入话题。
多态是面向对象最基本的概念之一,即要模糊父类和之类之间的区别,如何模糊呢?我们再来举网络上的那个例子:
class Aninal{ 叫;}//叫是动物的一个方法
class 猫 extend Animal{叫;}
class 狗 extend Animal{叫;}
Animal 狗 = new 狗();//这里用Animal来定义狗,没用用狗来定义,真正是狗叫还是猫叫,是
Animal 猫 = new 猫();//看赋予它的对象,这样真正实现了接口重用,一个对象可以调用
狗.叫();//Animal让它叫,而具体是谁在叫,到时候就看赋予它的子类是哪一个了,同时还有于
猫.叫();//扩展,想象一下,当添加了鸡之后,前面调用Animal的对象的方法都不用做任何修改。
具体在Java中的Collection的Iterator是运用多态最典型的例子,想象一下,Collection中有么多类(ArrayList,LinkedList,HashSet,TreeSet等),如果对应于每个类都写一个Iterarot,大家应该会知道这会有多臃肿了。但让Collection继承自Iterator(他们都属于接口),其他这些类也都继承自Iterator。还是举个例子:
Collection books = new HashSet();
books.add(15);
Iterator it =
books.iterator();//在定义it时用接口Iterator,但在初始化的时候用的却是 while(it.hasNext()) //HashSet类中实现的Iteratr()方法,即完全看子类赋予自己
{ //的是什么,这样就可以操作books中的对象。同时便于扩展
int book = (int)it.next();
System.out.println(book);
}
那我们知道了多态的概念之后,再来看泛型。List<T> list = new Arraylist<T>;这就是泛型的最常见的用法,其中T对应基本类型或自定义类,比如int,String。在我看来,引入泛型的本质就是为了安全,把编译时能发现的错误不带到运行时。比如上面那个books的例子,由于Collection中只要是继承自Object的对象都可以添加进去,所以你既可以存int,也可以存String,还可以存自定义类,当存进去无法被强制转换为int的对象时,int book = (int)it.next();这条语句在编译期时无法发现错误的,只有在运行时才能发现错误,这样对于整个系统都是不稳定的。而引入泛型之后,用T限制了传入list中的对象的类型,当传入不是T的类型时,程序就会提示错误,可以让我们更早的发现错误。
说了这么多,那我们来看看泛型和多态的关系。今天看到网上有个人说:泛型就是多态的一种特例,用多态即可实现泛型。乍一想好像挺有道理的,T可以根据传入的类型来确定其行为,这不就是多态吗?但又一想,多态是在继承层面上的,即根据实际运行时候来确定具体的实现,而泛型是当我们使用这个泛型类时候再去确定这个类里面的成员具体什么类型的,两者不是一个层次的,更不用提用多态实现泛型了。至于具体的实现大家可以自己去查查。