2019.3.14 多态和接口

多态

  • 什么是多态?
    多态就是事物存在的多种形态——当全部符合以下三种情况时 就是多态

1.有继承
2.有方法重写
3.有父类引用指向子类对象

  • 样例
    定义一个Person类作为父类

public class Person {

    private String name;    //姓名

    private int age;    //年龄

    public void eat(){

        System.out.println("吃吃吃");
    }


    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

定义一个Student类继承Person


public class Student extends Person {

    private double score;    //Student特有的属性

    public void exam(){    //Student特有的方法

        System.out.println("考试");
    }


    //重写eat方法
   @Override
    public void eat() {

        System.out.println("学生吃食堂");
    }




    @Override
    public String toString() {
        return "Student{" +
                "score=" + score +
                '}';
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
}

定义主函数MainClass


public class MainClass {

    public static void main(String[] args) {

        Student student = new Student();    //子类正常创建对象

        student.setName("张三");
        student.setAge(14);
        student.setScore(100);

        student.eat();
        
             //p:父类引用  Student:子类对象
        Person p = new Student();    //父类引用指向子类对象
        p.eat();

    }
}

上述MainClass中,p是Person类的一个引用,指向的是子类Student的对象,这个就是父类引用指向子类对象
student.eat();的输出与p.eat();的输出是一样的

  • 总结:
    1.父类的变量可以引用子类的对象。
    2.当一个方法的参数类型是某个类(Person)的时候,那么不仅仅可以把这个类创建的对象传入方法,
    也可以把这个类和它的子类创建的对象传入方法。注:传的都是对象
    3.使用多态之后,只可以使用父类的方法,如果非要使用子类方法,必须强制类型转换。

对象与引用

使用上述Person类和Student类,在MainClass中新建引用


public class MainClass {

    public static void main(String[] args) {

        Student student = new Student();    //子类正常创建对象

        student.setName("张三");
        student.setAge(14);
        student.setScore(100);

        Student s1 = student;
        s1.setScore(200);
        System.out.println(student.getScore());
    }
}

那么此时的输出score为多少?
答案为200。

Student s1 = student;这句代码的意思是:新建一个变量s1也可以访问student对象——这个就叫做增加一个对“对象的”引用;
这个s1复制的是对象student的内存地址,即s1也可以操作地址中的数据。
举个例子,我有一个大名叫刘子博 这个就相当于student,我还有一个外号,那么这个外号就相当于是s1。
student和s1中存放的 都是对象Student的地址,s1和student做的修改,都是对这个地址中的东西进行修改,所以上述例子中score的输出为200。
具体图解如图所示:

注意:一个对象可以有多个引用,可以有多个变量操作同一个对象;当一个对象没有任何变量引用时,就会销毁。

当在MainClass中定义一个方法:


public class MainClass {

    public static void main(String[] args) {

        Student student = new Student();

        student.setName("张三");
        student.setAge(14);
        student.setScore(100);
            
        Person person = new Student();
        test(student);        //主函数调用的test方法
    }
    
    public static void test(Person person){

        person.eat();
        System.out.println(person.getName());
    }
}

此时,主函数中调用的test方法的参数可以写什么?
答:因为父类可以引用子类,所以test里可以放student,因为studnet是Person的父类
test函数括号中的参数是person 因为student包括于person 所以test也可以加student。

接口

  • 啥是接口?
    java语言里面使用interface来声明一个接口,接口其实是一个特殊的抽象类,在接口里面的方法全部都是抽象的。
    接口代表的是一种能力;
    接口代表的是一种约定;
    能力:
    引用许超飞的Java接口这篇博客中的蜘蛛侠例子:
    需求:现在要创造一个蜘蛛侠。人有“唱歌”和“考试”的功能,蜘蛛有“爬行”和“吐丝”的功能。
    分析:首先蜘蛛侠是一个人,他有蜘蛛的能力。按照面向对象思想,可以将人和蜘蛛分别定义成抽象类。但是,不能让蜘蛛侠在继承人的同时又继承蜘蛛。
    两个原因:一、蜘蛛侠不是蜘蛛,不符合继承中 【is a】的关系;
    二、Java只支持单继承。如何解决这个问题呢?这时就要用到接口,接口是【has a】的关系。可以将蜘蛛的行为能力定义为接口,让蜘蛛侠继承人,实现蜘蛛的行为能力的接口。

    样例:
    新建一个接口“USB“


    public interface USB {
    
        void charge();    //充电
        void transfer();    //传输
}
新建一个Computer类:

import java.io.Serializable;    //有这个Serializable接口才能数据写到本地

public class Computer implements USB, Serializable {

    private String name;
    private int size;

    @Override
    public String toString() {
        return "Computer{" +
                "name='" + name + '\'' +
                ", size=" + size +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }


    //接口的实现
    @Override
    public void charge() {                  //所有的抽象方法都要实现

        System.out.println("充电");           //这个地方才是所谓的"实现"
    }

    @Override
    public void transfer() {

        System.out.println("传输数据");
    }
}

注意:在类中将接口中的抽象方法重写才是接口的"实现"。

  • 继承于接口的比较

    • 1.继承的不足:
      • (1)继承会导致继承树太深从而降低方法调用的效率(继承树太深是所有面向对象语言的缺点);
      • (2)不够灵活,父类的方法一定会被子类继承;
    • 2.接口的优势:
      • (1)一个类可以实现多个接口
      • (2)可以隐藏实现
  • 接口和多态

    • (1)接口不能创建对象,只能被类来实现;
    • (2)接口作为类型的变量,可以引用实现了该接口的对象;
  • 关于接口的多态

    新建一个接口“HDMI”


public interface HDMI {

    void transferVideo();

    void transferAudio();

}

新建一个显示器类Monitor,并实现HDMI接口


public class Monitor {

    //显示器的显示需要有HDMI提供图像
    public void display(HDMI hdmi){

        hdmi.transferVideo();
        hdmi.transferAudio();
        System.out.println("开始显示图像和声音");
    }
}

在上述的Computer类中实现HDMI接口


@Override
    public void transferVideo() {

        System.out.println("传输视频");
    }

    @Override
    public void transferAudio() {

        System.out.println("传输音频");
    }

当在MainClass中新建对象
HDMI hdmi = new Computer;
那么hdmi.可以直接调用HDMI中接口的方法

hdmi.transferAudio();
hdmi.transferVideo();
当想使用hdmi.调用USB中接口的方法时,需要强制转换类型

((Computer) hdmi).charge();

当在MainClass中新建对象
Computer com = new Computer();
Monitor monitor = new Monitor();
那么
monitor.display()的小括号中可以填实现了/Monitor类用的接口HDMI/的任何一个东西
比如
monitor.display(com); 意思是电脑输出的东西显示到显示器上 可以理解为接口就是连接设备的线?

代码及工程

链接:https://pan.baidu.com/s/1hCzEeCRpidSycEx1cr3Qcg
提取码:onnr

posted @ 2019-03-14 16:23  仲夏今天也在写前端  阅读(171)  评论(1编辑  收藏  举报