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.继承的不足:
-
接口和多态
- (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