普通类实现的问题
假设“猫”、“狗”和“鸟”等类各自实现其吃饭、喝水、玩耍和洗澡等方法,虽然不同动物吃的饭、喝的水、玩耍项目和洗澡水热度等要求不尽相同,但养这些动物的人每天对待这些动物的业务逻辑是完全一致的。比如喂猫吃饭、喝水,和猫一起玩和给猫洗澡,对狗和鸟实现的也是这些操作。如果不考虑代码可读性和可维护性的话,可能会得到下面的代码。
public class Cat{
public String name = "cat";
public void cat_eat(){}
public void cat_drink(){}
public void cat_play(){}
public void cat_bath(){}
}
public class Dog{
public String name = "dog";
public void dog_eat(){}
public void dog_drink(){}
public void dog_play(){}
public void dog_bath(){}
}
public class Bird{
public String name = "bird";
public void bird_eat(){}
public void bird_drink(){}
public void bird_play(){}
public void bird_bath(){}
}
public class Test{
public static void main(String args[]){
Cat cat = new Cat();
Dog dog = new Dog();
Bird bird = new Bird();
cat.cat_eat();
cat.cat_drink();
cat.cat_play();
cat.cat_bath();
dog.dog_eat();
dog.dog_drink;
dog.dog_play();
dog.dog_bath();
bird.bird_eat();
bird.bird_drink();
bird.bird_play();
bird_bath();
}
}
显然,直接调用会产生许多重复代码,使得主业务逻辑显得非常混乱。
抽取出feed方法提高主业务逻辑可读性
既然我们知道,一定是eat、drink、play和bath,那创建一个方法feed接收这些对象,然后统一调用这些操作可不可以呢。这当然是一个很好的解决思路,但是,上面我们看到,cat、dog和bird关于这几个是完全不相同的类,而其各自动作的方法名是不一致的(可能有人会觉得,怎么不一致呢,改一下就可以了。那假设一个团队共同完成一个项目,不同人各自实现不同动物应该如何可靠地保证一致呢?贴个纸条在电脑上或者写在备忘录里?那万一需要遵守的规范很多呢,显然是不现实的)。所以按照现在的类定义直接抽取出一个feed方法是不可能的。
降低重复代码的需求
有没有一种办法,可以通过定义一个feed方法,用一套统一的eat、drink、play和bath逻辑实现降低对不同动物方法调用导致的代码重复呢。要实现这个需求需要满足两点:1.保证所有动物的方法都是同名的,这样不论是哪个动物都可以调用同一个方法。2.需要有一个引用可以接受所有动物对象并统一调用这些对象的方法。
使用抽象类实现
假设定义“animal”抽象类,并定义抽象方法eat、drink、play和bath,让所有动物都去实现“animal”抽象类,会有什么效果呢。首先,因为所有动物都实现了抽象类定义的抽象方法,所以这些动物对于相同操作的方法都一定是同名的,这就满足了第一点要求。其次,抽象类虽然不能实例化,但它是能定义引用来指向其实现类的对象的,并且可以调用这些实现类对象所实现的方法,这就满足了第二点。因此,现在我们可以在person类中设计一个feed方法接收实现类对象作为animal对象使用,并且用一致的方法名调用每个实现类对象的方法了。在feed中只需要依次调用animal.eat(); animal.drink(); animal.play();animal.bath();方法即可。这减少了重复代码,降低了耦合度,业务逻辑更清晰更便于维护。
示例代码
public abstract class animal(){
private String name;
public abstract void eat();
public abstract void drink();
public abstract void play();
public abstract void bath();
}
public class Cat extends animal(){
//重写所有抽象方法
}
public class Dog extends animal(){
//重写所有抽象方法
}
public class Bird extends animal(){
//重写所有抽象方法
}
public static void main(String args[]){
Cat cat = new Cat();
Dog dog = new Dog();
Bird bird = new Bird();
feed(cat);
feed(dog);
feed(bird);
}
public static void feed(animal a){
a.eat();
a.drink();
a.play();
a.bathe();
}
总结
简单地说,抽象类起到了实现类的规范作用。基于这种规范,可用一个抽象类的引用统一调用所有实现类的方法,即实现多态。最后补充一点,抽象类或接口都有规范的作用,并且都可以实现多态,实际上,接口比抽象类使用得更多。