继承和多态
- 继承和多态是什么?
- 继承实现
- 方法覆盖
- 多态实现
- instanceof
- 子类构造方法
- 抽象类
继承和多态是什么?
继承是对已有类的域和方法的复用,并可在此基础上,添加新的操作。
多态是一个变量可以指示多种实际类型的现象,在运行时能够自动选择调用哪个方法的现象称为动态绑定。
继承实现
继承通过在类定义后面添加 extends 类名 实现,Java只支持单继承
public class Dog {
private int cost;
public void setCost(int cost) {
this.cost = cost;
}
}
class LuckyDog extends Dog {
private String name;
public void setName(String name) {
this.name = name;
}
}
继承后,子类会获得除父类构造方法外的所有成员方法和成员变量,如下,LuckyDog继承了Dog的cost和setCost()方法,并新增了name和setName()方法:
Dog dog = new Dog();
dog.setCost(1000);
LuckyDog luckyDog = new LuckyDog();
luckyDog.setName("luckyDog");
luckyDog.setCost(2000);
方法覆盖
子类可以通过重写父类的方法覆盖原来的方法,覆盖时子类方法的可见性不能低于父类方法,子类方法访问父类方法或属性需要使用super关键字,如LuckyDog在Dog的基础上贵1000:
public class Dog {
private int cost = 1000;
public int getCost() {
return cost;
}
}
class LuckyDog extends Dog {
public int getCost() {
return super.getCost() + 1000;
}
}
多态实现
多态实现的前提是父类子类拥有相同的方法,即存在方法覆盖,如上面的实例,用父类Dog的变量luckyDog指向子类对象new LuckyDog(),调用getCost()方法将打印2000,但多态情况下不能使用子类独有的方法:
Dog dog = new Dog();
System.out.println(dog.getCost());
Dog luckyDog = new LuckyDog();
System.out.println(luckyDog.getCost());
instanceof
在下面的继承结构中
public class Dog {
}
class LuckyDog extends Dog {
public int getCost() {
return 1000;
}
}
通过多态,子类数组可转为父类数组,但此时,子类变量luckyDogs和父类变量dogs指向同一个数组:
LuckyDog[] luckyDogs = new LuckyDog[3];
Dog[] dogs = luckyDogs;
若赋值
dogs[0] = new Dog();
就会误将Dog对象存储到LuckyDog对象的数组中,当调用子类特有方法时会产生错误,如
for (int i = 0; i < luckyDogs.length; i++) {
luckyDogs[i].getCost();
}
即将父类转为子类时,可能会造成错误,这时需要用instanceof关键字判断
for (int i = 0; i < luckyDogs.length; i++) {
if (luckyDogs[i] instanceof LuckyDog) {
luckyDogs[i].getCost();
}
}
子类构造方法
如果子类构造方法没有调用父类的构造方法,则会隐式自动调用父类无参构造方法,同时子类构造方法可以通过super显式调用父类的构造方法(必须放在第一句):
public class Dog {
private int cost;
public Dog() {
}
public Dog(int cost) {
this.cost = cost;
}
}
class LuckyDog extends Dog {
public LuckyDog() {
//super();
}
public LuckyDog(int cost) {
super(cost);
}
}
抽象类
当一个方法对父类没有意义,但其对所有具体子类都有意义(如下:抽象的Person没有名字可以返回),可以通过abstract关键字将其改为抽象方法
拥有一个或多个抽象方法的类为抽象类,若其子类不是抽象类,就应该实现抽象父类中的所有抽象方法
abstract class Person{
private String name;
abstract String getName();
}
不含抽象方法的类也可申明为抽象类,抽象类不能实例化,即不能通过new创建抽象类实例,但可以引用其子类实例