多态的使用
多态的引入
假设你想创建一个Dog专用List
public class MyDogList{
private Dog[] dogs = new Dog[5];
private int nextIndex = 0; // 增加新的Dog就加一
public void add(Dog d) {
if (nextIndex < dogs.length) { // 如果没有超过dogs的上线
dogs.[nextIndex] = d;
System.out.println("Dog added at" + nextIndex);
nextIndex++; // 递增计数
}
}
}
但是,现在也要写出Cat用的
-
另外创建一个单独的MyCatList来处理Cat对象 (这样显然是不好的)
-
创建一个单独的DogAndCatList类,用addCat(Cat c) 与 addDog(Dog d) 来同时处理两个不同的数组实例,但是这样也不是很好
-
编写一个不同的AnimalList类让他来处理Animal所有的子类
// 自己创建一个Animal通用List public class MyAnimal { // 这不是在创建Animal对象,只是保存Animal的数组对象 private Animal[] animals = new Animal[5]; private int nextIndex = 0; public void add(Animal a) { if (nextIndex < animals.length) { animals[nextIndex] = a; System.out.println("Animal added at" + nextIndex); } } } public class AnimalTestDrive{ MyAnimalList list = new MyAnimalList(); Dog d = new Dog(); Cat c = new Cat(); list.add(a); list.add(c); }
对象之母
Java中所有的类都是从Object这个类继承出来的
Object是所有类的源头,他是所有类的父类
可以把自己的代码想象成
public class Dog extends Object(){}
没有直接继承过其他类的类会是隐含的继承对象
所以就算Dog或Cannie没有直接extend对象,还是会通过Animal来继承对象
终极对象
// 一.equals
Dog a = new Dog();
Cat c = new Cat();
if (a.equals(c)) {
System.out.println("true");
} else {
System.out.println("true");
}
// 输出结果为false
// 二.getClass()
Cat c = new Cat();
System.out.println(c.getClass());
// 输出结果是 class Cat
// 三. hasCode()
Cat c = new Cat();
System.out.println(c.hasCode());
// 输出结果是 8202111
// 四.toString()
Cat c = new Cat();
System.out.println(c.toString());
// 输出结果是 Cat@7d277f
- Object这个类是抽象类嘛?
- 不是
- Object类是具体的,怎么会允许有人去创建Object的对象?
- 因为有时候就是会需要一个通用的对象.一个轻量化的对象,他是最常见的用途是在线程的同步化上
使用Object类型的多态引用是会付出代价的
ArrayList<Object> myDogArrayList = new ArrayList<Object>(); // 保存对象的
Dog aDog = new Dog();
myDogArrayList.add(aDog);
如果是如上述代码一样存储Dog对象,那么取出Dog对象的时候会引发什么事情?
Dog d = myDogArrayList.get(0);
这段代码将无法编译!对ArrayList 调用get()方法会返回Object类型,编译器无法确认它是Dog!!!
任何ArrayList去除来的东西都会被当作Object类型的引用而不管它原来是什么
public void go(){
Dog aDog = new Dog();
Dog sameDog = getObject(aDog);
}
public Object getObject(Object o) {
return o;
}
无法通过编译,虽然这个方法会返回一个Dog,但是编译器认为这只能赋值给Object类型的变量
public void go(){
Dog aDog = new Dog();
Object sameDog = getObject(aDog);
}
public Object getObject(Object o) {
return o;
}
这样会过关,因为你可以赋任何值给Object类型的引用,平且每个东西都能对Object通过IS-A测试
编译器是根据引用类型来判断有哪些method可以调用,而不是根据Object确实的类型
就算你知道对象有这个功能,编译器还是会把它当作一般Object来看待,编译器只管引用的类型,而不是对象的类型
上述的sameDog就不可以在调用Dog身上的方法了,只能引用Object身上的方法
“多态"意味着"很多形式”
你可以把Snowboard当作Snowboard或者Object
当你把对象装进ArrayList时,不管它原来是什么,你只要把它当作是Object.
从ArrayList取出引用时,引用类型只会是Object
转化为原来的类型
Object o = al.get(index);
Dog d = (Dog) o; // 将类型转化成Dog
d.roam();
如果不能确定它是Dog可以使用instanceof这个运算符来检查,若是类型转化错误,会遇到ClassCastException异常并且终止.
if (o instanceof Dog) {
Dog d = (Dog) o;
}
g) o; // 将类型转化成Dog
d.roam();
如果不能确定它是Dog可以使用instanceof这个运算符来检查,若是类型转化错误,会遇到ClassCastException异常并且终止.
```Java
if (o instanceof Dog) {
Dog d = (Dog) o;
}