在我们学过了继承和多态后,我们看到如果子类重写了父类的方法,那么运行时就不会去管父类里的这个方法的内容了,那么我们是否可以用一种方法去省略父类中的内容而不报错呢?比如有一个的代码:
class Animal{
public void eat(){
System.out.println("动物吃东西");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
}
class Test{
public static void main(String[] args){
Animal animal=new Dog();
animal.eat();
}
}
这个代码运行过后的结果是 狗吃骨头 ,而不是 动物吃东西 ,因此我们可以猜测在运行时是从子类开始,再到父类终止。因此我们想:父类的方法是否可以省略?
我们再写一个代码:
class Animal{
public void eat(){
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
}
class Test{
public static void main(String[] args){
Animal animal=new Dog();
animal.eat();
}
}
再看这个代码,结果还是狗吃骨头,而且父类里的方法似乎已经省略到了最简,如果再省略掉大括号的话,那么编译时就会报错。看起来好像已经是最简化了,但实际上还有一种方法可以使其省略大括号,这个方法就叫做抽象方法,抽象方法要用 abstract 修饰。如下:
public abstract class Animal{
public abstract void eat();
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
}
class Test{
public static void main(String[] args){
Animal animal=new Dog();
animal.eat();
}
}
但我们明明只改变抽象方法,为什么类也要改成抽象的呢?因为当你定义了一个抽象方法后,如果这个类不是抽象类,编译时就会报错。因此我们要知道,有抽象方法的类一定要是抽象类。那么我们就有疑问了,抽象类是否一定要有抽象方法呢?其实不然,抽象类里还可以有其他方法,如:
abstract class Animal{
static void feed();
default void drink();
}
这些方法不是抽象方法,但依旧可以在抽象类中存在,而且系统不会报错。所以我们又知道了:抽象类中的方法并不一定要有抽象方法。我们再来继续看一个代码:
public abstract class Animal{
public abstract void eat();
public abstract void walk();
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
}
class Test{
public static void main(String[] args){
Animal animal=new Dog();
animal.eat();
}
}
这个代码看起来好像没什么问题,但当你编译时它还是会报错。原因就是对于抽象类中的方法,子类必须要全部重写抽象方法,如果没有写全,则会报错。但对于Dog类,我们其实还可以给它定义一个子类,那么Dog类就会变成一个抽象类,便可以不用重写Animal类的抽象方法,而是由这个子类重写抽象方法。
所以我们又知道了:若一个类继承自抽象类必须重写抽象方法,否则该类也是抽象类。
我们可以看到抽象类的强制性,如果你没有在子类重写抽象方法,它就会直接报错,这也可以在我们写代码时很好地提醒我们。
对于抽象类,其中的public abstract 可以当作 interface(接口),接口的定义和类的定义类似,我们可以看看接口的形式:
interface A{
void eat();
void walk();
}
而接口的一些性质实际上和抽象类也是类似的,接口中除了可以用抽象方法外,还可以用其他方法,如:static void feed(); 等等,但在这里我就不多讲了。
而接口有所不同的是,接口只有定义而没有实现,如果你想要实现里面的方法,那么必须要有子类来实现(implements)它。如:
interface A{
void eat();
}
class Dog implements A{
public void eat(){
System.out.println("狗吃骨头");
}
}
class Test{
public static void main(String[] args){
A a=new Dog();
a.eat();
}
}