抽象类
如果一个class定义了方法,但没有具体执行代码,这个方法就是抽象方法,抽象方法用abstract修饰。
因为无法执行抽象方法,这个类必须申明为抽象类(abstract class),所有使用abstract修饰的类就是抽象类。
抽象类不能进行实例化,其本身被设计成只能用于被继承,因此,抽象类可以强迫子类实现其定义的抽象方法,否则编译会报错。抽象类是一直对子类的规范。
例如,Car类定义了抽象方法run(),那么,在实现子类Track的时候,就必须覆写run()方法:
public class Main {
public static void main(String[] args) {
Car c = new Track();
p.run();
}
}
abstract class Car {
public abstract void run();
}
class Track extends Person {
@Override
public void run() {
System.out.println("Track.run");
}
}
接口
在抽象类中,抽象方法本质上是定义接口规范:即规定高层类的接口,从而保证所有子类都有相同的接口实现,在这种情况下,就跟能体现多态的性质。
abstract class Car {
public abstract void run();
public abstract int getWeight();
}
对这种抽象类,我们可以改写成接口:interface
interface Car {
void run();
int getWeight();
}
在interface中,所有方法默认添加是public abstract,因此可以不用写出来。当一个类继承自接口时,关键词“extends”换成了“implements”。
在Java中,一个类只能继承一个父类,不能继承多个类,但却能继承多个接口:
class Track implements Car, Transport{...
}
接口继承
一个interface可以继承自另一个interface。interface继承自interface使用extends,它相当于扩展了接口的方法。
interface Transport {
void open();
}
interface Car extends Transport {
void run();
int getWeight();
}
default方法
在接口中,可以定义default方法。例如,把Car接口的run()方法改为default方法:
public class Main {
public static void main(String[] args) {
Car c = new Track("DF-580");
c.run();
}
}
interface Car {
String getName();
default void run() {
System.out.println(getName() + " run");
}
}
class Track implements Car {
private String name;
public Track(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
实现类可以不必覆写default方法。default方法的目的是,当我们需要给接口新增一个方法时,会涉及到修改全部子类。如果新增的是default方法,那么子类就不必全部修改,只需要在需要覆写的地方去覆写新增方法。
default方法和抽象类的普通方法是有所不同的。因为interface没有字段,default方法无法访问字段,而抽象类的普通方法可以访问实例字段。