多态指的是同一个对象,在不同时刻表现出的多种形态。
例如,当所用种类的动物统称为一个对象时,那么这个对象的名称就为动物。每一个种类的动物又继承于动物这个总的类。当总的类遇到猫类表现出的形态就猫类,遇到狗类表现出的形态就是狗类。
多态的前提条件
1、有继承或实现关系 例如 public class Dog(子类) extends Animal(父类)
2、有方法的重写 父类的行为不能准确描述子类的行为,那么就需要将父类的行为(方法)重写
3、有父类引用指向子类对象 例如:Animal animal=new Dog();
当有父类引用指向子类对象时,那么用父类类型的变量的去访问属性和行为时需要注意:
1、当用animal去访问成员变量时,规则是编译看左边,执行看左边。
2、当用animal去访问成员方法时,规则是编译看左边,执行看右边。(当父类中有这个方法时,才能去执行子类中的这个方法。如果父类中没有这个方法那么报错)
优点:定义方法的时候,使用父类型作为参数,将来在使用的时候,使用具体的子类型参与操作
缺点:当子类有自己的特有的行为时,不能通过父类引用去访问子类中特有的行为。
那么当用父类引用去指向子类对象时,就发生了转型
因为 = 右边的是子类对象,赋值给了 = 左边的父类引用类型,这是类型的自动转换。类似于基本数据类型中的int和double类型都参与运算时,int会自动转换为double类型。
而 = 左边的无法随意的转换为 = 右边的类型,例如上面的animal是Animal类型接受的子类(Dog类型)对象。此时animal只能向下转换为Dog类型的引用类型,并且要加强制转换的类型。例如animal向下转换只能强制转换为Dog类型的。例:Dog dog=(Dog)animal;
抽象类
抽象类就是将父类中的一些行为不知道确切的做的什么事时,那么就需要将这些行为写成抽象方法。
注:1、当一个类中有了抽象方法,那么这个类就只能为抽象类。
2、当一个类为抽象类时,类里面可以没有抽象方法。
3、抽象类和抽象方法都必须加关键字abstract。
抽象类 语法:public abstract class 类名{}
抽象方法 语法:public abstract 返回值类型 方法名(){}
4、当一个类为抽象类时,那么这个类不能被实例化(既不能创建这个类的对象)。原因:当一个类为抽象类时,它的方法大概率为抽象方法,加入创建这个类的对象,但这个对象都没有具体的行为,那么创建的这个对象也没有什么实际的意义。
5、抽象类的子类要么重写父类中所有的抽象方法,要么也是抽象类。
抽象类中也可以有变量、常量、构造方法、抽象方法。变量是用于抽取子类共同的属性;虽然父类是抽象类不能实例化,但构造方法可以用于子类构造从父类继承的属性;构造方法用于子类实现自己的行为。
接口
接口就是抽象的概念,是一中规范标准,也是将一些抽象方法的抽取。当类满足接口的规范时就可以使用这个接口。
接口的建立 类似于类的建立 语法:public interface 接口名{}
接口中的方法只能是抽象方法(JDK8以前) 抽象方法可以省略 public abstract(因为系统默认有)
类实现接口 语法: public class 类名 implements 接口名{}
接口的实现类要么是抽象类,要么就重写实现的接口中的所有抽象方法。
接口于类的关系,实现关系,一个类可以实现多个接口;也可以在继承一个父类时实现多个接口。
接口与接口的关系:继承关系,接口可以继承一个或多个接口。
例题:
需求:请采用面向对象的思想实现木门和电动报警门的案例,并在测试类中进行测试 木门 成员变量:宽,高,品牌 成员方法:开门,关门 电动报警门: 成员变量:宽,高,品牌 成员方法:开门,关门,报警
//门类
private double width; //宽
private double height; //高
private String brand; //品牌
public Door() {
}
public Door(double width, double height, String brand) {
this.width = width;
this.height = height;
this.brand = brand;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public abstract void open();
public abstract void close();
//电动报警门 继承与门 类
public ElectricAlarmDoor() {
}
public ElectricAlarmDoor(double width, double height, String brand) {
super(width, height, brand);
}
@Override
public void open() {
System.out.println("门可以打开");
}
@Override
public void close() {
System.out.println("门可以关闭");
}
@Override
public void alarm() {
System.out.println("门可以报警");
//木门 继承与门这个类
public WoodDoor() {
}
public WoodDoor(double width, double height, String brand) {
super(width, height, brand);
}
@Override
public void open() {
System.out.println("门可以打开");
}
@Override
public void close() {
System.out.println("门可以关闭");
}
//报警的接口
public interface Alarm {
public abstract void alarm();
}
测试:
WoodDoor woodDoor = new WoodDoor(1.5, 2.2, "金凯德");
System.out.println("宽:" + woodDoor.getWidth() + "m " + "高:" + woodDoor.getHeight() + "m " + "品牌:" + woodDoor.getBrand());
woodDoor.open();
woodDoor.close();
ElectricAlarmDoor ead=new ElectricAlarmDoor(4.4,2.5,"金凯德");
System.out.println("宽:" + ead.getWidth() + "m " + "高:" + ead.getHeight() + "m " + "品牌:" + ead.getBrand());
ead.open();
ead.close();
ead.alarm();