zoukankan      html  css  js  c++  java
  • 多态的理解

    什么是多态

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

    解释:见如下代码

      不同类的对象:子类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()就行了。

  • 相关阅读:
    触摸屏单点USB HID设置(老外写的 我看着基本没什么问题)
    USB 字段和包格式(1)
    LPC1343整理
    USB枚举和HID枚举实例(6)
    USB/HID设备报告描述符详解 (3)
    C# 值类型与引用类型(1)
    USB组合设备(5)
    千里之行,始于脚下
    c#中的结构体类型
    sqlmap 学习指南
  • 原文地址:https://www.cnblogs.com/zfyang2429/p/10302895.html
Copyright © 2011-2022 走看看