抽象方法
声明:仅进行声明,没有方法体。
abstract void f();
抽象类:包含抽象方法的类。由于抽象类中包含无具体实现的方法,因此不能用抽象类创建对象。抽象类可以有成员变量和普通成员方法。
如果一个类继承了抽象类,并且希望创建该类的对象,那么必须为基类中的所有抽象方法提供具体实现。如果不这样做,那么导出类也必须定义为抽象类,并且编译器会强制使用 abstract
关键字来限定这个类。
使用抽象类时需注意以下几点:
- 抽象类不能被实例化,实例化工作应由其子类完成。
- 抽象方法必须由子类重写。
- 只要类中包含一个抽象方法,该类就必须定义为抽象类,无论是否还有其他方法。
- 抽象类中可以包含具体方法,也可以不包含抽象方法。
- 子类中的抽象方法不能与父类的抽象方法同名。
abstract
不能与final
并列修饰同一个类。abstract
不能与private
、static
、final
或native
并列修饰同一个方法。
抽象类和普通类的主要区别有三点:
1. 抽象方法必须为 public
或 protected
(因为如果为 private
,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为 public
。
2. 抽象类不能用来创建对象。
3. 如果一个类继承了抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为抽象类。
在其他方面,抽象类和普通类没有区别。
接口:
interface
关键字用于定义完全抽象的类,接口中的所有方法都不能有具体的实现,即接口中的方法必须都是抽象方法。从这里可以看出接口和抽象类的区别,接口是一种极度抽象的类型,比抽象类更加“抽象”,并且一般情况下不在接口中定义变量。
实现接口的类通过 implements
关键字实现接口中 所有 的方法。Java 不支持多继承,但可以通过实现多个接口来弥补这一不足。
接口继承的关系如下:
class ClassName implements Interface1, Interface2, ... { }
在使用接口时需注意以下几点:
- 接口
interface
前可以用public
修饰,不添加public
的情况则只有包访问权限。当实现一个接口时,如果没有public
修饰,默认为public
。 - 接口中可以定义“成员变量”,实际上是不可变的常量,因为接口中的“成员变量”会自动变为
public static final
。可以通过类名直接访问:ImplementClass.name。 - 接口中不存在实现的方法。
- 实现接口的非抽象类必须实现该接口的所有方法。抽象类可以不实现。
- 不能使用
new
操作符实例化一个接口,但可以声明一个接口变量,该变量必须引用一个实现该接口的类的对象。可以使用instanceof
检查一个对象是否实现了某个特定的接口。例如:if (anObject instanceof Comparable) {}
。 - 在实现多个接口时一定要避免方法名的重复。
其中对于第二点的说明,接口的成员特点如下:
A: 成员变量只能是常量,默认修饰符为 public static final
。
B: 成员方法只能是抽象方法,默认修饰符为 public abstract
。
如图报错是因为接口中成员变量自动为 static final
修饰,所以需要赋予初始值。
改为如下即不报错
抽象类与接口的区别:
1. 语法层面上的区别:
- 抽象类可以提供成员方法的实现细节,而接口中只能存在
public abstract
方法。 - 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是
public static final
类型。 - 接口中不能含有静态代码块及静态方法,而抽象类可以有静态代码块和静态方法。
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
2. 设计层面上的区别:
- 抽象层次不同。抽象类是对类的抽象,而接口是对行为的抽象。
- 跨域不同。抽象类所跨越的是具有相似特点的类,而接口却可以跨越不同的类。抽象类体现的是一种继承关系,要想使继承关系合理,父类和派生类之间必须存在“is-a”关系,即父类和派生类在概念本质上应该是相同的。对于接口则不然,并不要求接口的实现者和接口定义在概念本质上一致,仅仅是实现了接口定义的契约而已。
- 设计层次不同。对于抽象类而言,它是自下而上设计的,需要先知道子类才能抽象出父类;而接口则不同,它根本就不需要知道子类的存在,只需要定义一个规则即可,至于什么子类、什么时候怎么实现它一概不知。
参考资料:
https://www.cnblogs.com/dolphin0520/p/3811437.html
https://blog.csdn.net/chenssy/article/details/12858267