抽象类与接口类的异同
诞生过程
继承的诞生:
抽象的诞生:
父类没必要完全实现所有逻辑,也没必要创建一个父类时。
就只是单纯的想让各种各样的子类来完成不同的逻辑,则诞生了抽象类。
将父类的方法抽象出来,让子类继承父类后,重写父类中的方法。这里的抽象类就拥有了 “标准” 与 “规范” 的意思。
- 抽象类就好比一类规范的制定方;
- 而抽象类的子类就好比这一规范的实现方;
- 但是抽象类不完全抽象,因为它除了抽象方法外,还有成员属性。
- 且有时候就是只想制定一个纯粹的标准,让子类去实现抽象方法,不想让子类再继承别的东西,这时候 “接口类” 诞生了。
接口的诞生
接口 只有成员方法 ,没有成员属性 ,子类继承接口后唯一能做的就是重写方法;
public interface Runnable {
public abstract void run();
}
所以说,接口就是一种模板一种规范。接口规定好方法模板后,子类都必须按照该模板来实现方法。
所以接口就是定义接口,供子类实现的同时供调用方调用。
public static void printCollection(Collection collection) {
if(collection == null) {
return;
}
System.out.println("数据数量:" + collection.size())
}
public static void main(String[] args) {
printCollection(new ArrayList());
printCollection(new HashSet());
}
这里将方法 printCollection()
的参数定义成 Collection
接口类,调用方就可传入任何一个 Collection 的子类(如:ArrayList、HashSet)进来。
抽象与接口的异同
同
- 都可以定义抽象方法;
//抽象类
public abstract class Animal {
public abstract void eat();
}
//接口类
public interface class Runnable {
public abstract void run();
}
- 都不能创建本类对象,都需要通过子类进行实例化;
异
- 子类扩展继承时的方法不同;
//继承抽象
public class Dog extends Animal {}
//实现接口
public class Thread implements Runnable {}
- 抽象类可以实现接口,接口只能继承接口;
public abstract class Animal implements A {}
public interface Runnable extends A, B, C {}
- 一个类最多只能继承一个父类但是能实现多个接口;
public abstract class Pet extends Animal implements A, B, C {}
因而使用接口类来实现子类的灵活度更高。
- 接口只能定义
final
类型的静态常量(不能定义静态变量),抽象类可以定义成员属性;
public abstract class Animal {
protected String name;
public abstract void eat();
}
public interface class Runnable {
public static final name = "Dioxide.CN";
public abstract void run();
}
- 接口类没有构造器,抽象类有构造器。抽象类的构造器作用为:限定子类的构造行为;
public abstract class Animal {
protected String name;
protected Animal(String name) {
this.name = name;
}
public abstract void eat();
}
class Dog extends Animal {
//约束构造行为
public Dog(String name) {
super(name);
}
@Override
public void eat() {
System.out.println("开饭了");
}
}
- 从 Java8 开始,接口类可以使用
default
关键字来定义方法、也可以使用static
关键字来定义静态方法;
public interface class Animal {
void eat();
//不会强制子类去实现方法
default void defaultMethod() {
System.out.println("默认方法");
}
//不会强制子类去实现方法
static void staticMethod() {
System.out.println("静态方法");
}
}
- 从 Java9 开始,接口类可以使用
private
权限修饰符来定义方法;
public interface class Animal {
void eat();
default void defaultMethod() {
privateMethod();
privateMethod();
privateMethod();
}
private void privateMethod() {
System.out.println("私有方法");
}
}
何时调用
抽象类 | 接口类 | |
---|---|---|
定义 | 包含抽象方法的类 | 主要是抽象方法和静态常量的类 |
组成 | 构造器 抽象方法 普通成员方法、成员变量 静态方法、静态变量 常量 |
静态常量 抽象方法 default方法、静态方法(Java8) 私有方法(Java9) |
使用 | 子类继承抽象类(extends) | 子类实现接口类(implements) |
关系 | 子类只能继承一个接口类 抽象类可以实现多个接口类 |
子类可以实现多个接口 接口不能继承类但能继承多个接口类 |
选择 | 如果需要继承父类的成员变量,或者需要控制子类的实例化,则选抽象类 | 优先选择接口,避免单继承的局限 |
评论区