抽象类 vs 接口
我们知道,不同类之间公有的属性或方法,可以抽象成一个接口(Interfaces)。而抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现。
由于二者都描述了类的形状,因此我们在 TypeScript 中都可以使用它们来键入变量,所以可能会有同学困惑于二者的应用场景。
- 抽象类本质是一个无法被实例化的类,其中能够实现方法和初始化属性,而接口仅能够用于描述既不提供方法的实现,也不为属性进行初始化。
- 一个类可以继承一个类或抽象类,但可以实现(implements)多个接口
- 抽象类也可以实现接口
所以当我们仅需要用于描述类的形状而不需要统一抽象出来将之实现的时候,我们可以采用接口来进行描述。如果我们需要将通用的方法和属性提取出来统一实现和初始化的时候,我们应该采用抽象类进行提取。
假如我们要声明一个 Personal 类,具有 age 和 name 属性,同时拥有 say 和 sayHello 方法,同时 sayHello 方法不受其实例化影响永远返回 ‘hello’,我们可以这样做
// 声明 IPerson 接口,仅声明但不实现
interface IPerson {
name: string;
age: number;
say(): void;
sayHello():string;
}
// 声明 AbstractPerson 抽象类,并实现 sayHello 方法
abstract class AbstractPerson implements IPerson {
age: number;
name: string;
abstract say(): void;
sayHello() {
return 'hello'
}
}
// 继承自 AbstractPerson 抽象类
class Person extends AbstractPerson {
age: number;
name: string;
say() {
return 'hi'
}
sayHello() {
return 'hello'
}
}