多态的理解

什么是多态

定义:不同类的对象对同一个消息作出不同的响应。

解释:见如下代码

  不同类的对象:子类cat和子类dog

  同一个消息:调用eat()方法

  不同的响应:分别为 cat eat 和 dog eat

//父类Animal
public
class Animal { public void eat(){ System.out.println("animal eat"); } } //子类Cat public class Cat extends Animal{ @Override public void eat() { System.out.println("cat eat"); } } //子类Dog public class Dog extends Animal{ @Override public void eat() { System.out.println("dog eat"); } }

//测试
public class TestController {

public static void main(String[] args) {
Animal animal1 = new Cat();
Animal animal2 = new Dog();
animal1.eat();
animal2.eat();
}

}

结果:

cat eat
dog eat

由此引出多态存在的三个条件

多态存在的三个条件

1.有继承关系

Cat和Dog继承Animal

2.子类重写父类的方法

Cat和Dog重写父类Animal的eat方法

3.父类的引用变量指向子类对象

Animal animal1 = new Cat();
Animal animal2 = new Dog();

多态的作用

消除类型之间的耦合关系,即解耦。

举例:

你定义了一个接口,功能是存储文件。定义了一个下载工具类用来存储下载的文件。

//接口:存储文件
public interface SaveFile {
    void save(File file);
}

//下载工具类,有一方法为将下载的文件存储下来(调用上述接口)
public class DownLoadTools {

    public static void  downLoad(File file,SaveFile saveFile){
        saveFile.save(file);
    }

}

写了两个实现类,分别将文件存储在U盘和硬盘中。

//u盘存储
public
class UDisk implements SaveFile{ @Override public void save(File file) { System.out.println("u盘存储"); } }
//硬盘存储
public class HardDisk implements SaveFile{ @Override public void save(File file) { System.out.println("硬盘存储"); } }
public static void main(String[] args) {

        File file = new File("");

        SaveFile hardDisk = new HardDisk();
        SaveFile uDisk = new UDisk();

        DownLoadTools.downLoad(file,hardDisk);
        DownLoadTools.downLoad(file,uDisk);

}

结果:

硬盘存储
u盘存储

此时如果需要将下载文件存储到CD中,只需要定义一个CDDisk实现类实现saveFile接口,无需更改downLoadTools下载工具类,这样downLoadTools类就不依赖于任何具体的类,这样就解除了与其他类之间的耦合性;

//CD存储
public class CdDISK  implements SaveFile{
    @Override
    public void save(File file) {
        System.out.println("cd存储");
    }
}

//测试
public class Test {
    public static void main(String[] args) {

        File file = new File("");

        SaveFile hardDisk = new HardDisk();
        SaveFile uDisk = new UDisk();
        SaveFile cdDisk = new CdDISK();

        DownLoadTools.downLoad(file,hardDisk);
        DownLoadTools.downLoad(file,uDisk);
        DownLoadTools.downLoad(file,cdDisk);

    }
}

结果:

硬盘存储
u盘存储
CD存储

补充说明1:只要一个方法操作的是类而非接口,那么你只能使用这个类及其子类。如果你想要将这个方法应用于不在此继承结构中的某个类,那么你就触霉头了。接口可以在很大程度上放宽这种限制(如上述的SaveFile接口),因此,他使我们可以编写可复用性更好的代码。——引用《thinking in java》的某一些话。

补充说明2:简单地说就是,没有多态,那么等号左边是啥右边就得是啥,这就叫耦合,有了多态,左边是父类(或者接口),右边是子类(或实现类),我只管调用父类(或者接口)里面的方法就是了,至于你子类(实现类)怎么去实现,那是你的事,你要修改一下实现,你只管去把子类(实现类)换掉,我这边一行代码都不用变,这就解耦了。

多态用在什么地方?

1.用在方法的参数中

情景:一个人养了一只宠物,现在调用person的keepPet(参数1)方法需要知道是什么宠物在吃饭

参数1给的是父类Animal的话,那么无论你后来需要养Lion,Tiger,Panda等等,都可以直接继承父类Animal,而Person的keepPet(参数1)方法不需要改变

若参数1给的是具体的Cat,Dog,Lion等等,那么你养了几只宠物,就需要写几个keepPet()方法,如keepPet(Cat cat),keepPet(Dog dog),keepPet(Lion lion)等。

public class Person {
  //参数给的是父类Animal,那么调用的时候传参就可以是父类Animal的任意子类对象
public void keepPet(Animal animal){ animal.eat(); } } //父类Animal public class Animal { public void eat(){ System.out.println("animal eat"); } } //子类cat public class Cat extends Animal{ @Override public void eat() { System.out.println("cat eat"); } } //子类dog public class Dog extends Animal{ @Override public void eat() { System.out.println("dog eat"); } }

//测试
public class TestController {

public static void main(String[] args) {
Animal animal1 = new Cat();
Animal animal2 = new Dog();
Person person = new Person();
person.keepPet(animal1);
person.keepPet(animal2);
}

}

结果:

cat eat

dog eat

2.用在方法的返回类型中

前面的cat对象和dog对象都是直接new()的,现在设计一个工厂类,专门生产Animal

//以前
Animal animal1 = new Cat(); Animal animal2 = new Dog(); Person person = new Person(); person.keepPet(animal1); person.keepPet(animal2);
//现在
Animal animal1 = AnimalFactory.animalFactory("cat"); Animal animal2 = AnimalFactory.animalFactory("dog"); Person person = new Person(); person.keepPet(animal1); person.keepPet(animal2);
//工厂类方法,返回值类型是父类Animal,那么返回值就可以是Animal的所有的子类
public
class AnimalFactory { public static Animal animalFactory(String animalName){ if(animalName.equals("cat")){ return new Cat(); }else if(animalName.equals("dog")){ return new Dog(); }else{ System.out.println("暂无该种动物"); return null; } } }

这实际上是设计模式中的工厂模式,当然如果类是一个完全独立的类,无相似的类,那么直接new()就行了。

 

posted @ 2019-01-22 11:36  吹灭读书灯  阅读(2573)  评论(0编辑  收藏  举报