interface,class,和abstract class这3个概念,既有联系,又有区别,本文尝试着结合官方文档来阐述这三者之间的关系。
1. Declaration Merging
Declaration Type
Namespace
Type
Value
Namespace
X
X
Class
X
X
Enum
X
X
Interface
X
Type Alias
X
Function
X
Variable
X
首先我们来讲一下上面这张表格,当我们第一列的关键字进行声明时,我们在做什么。
1namespace job { 2 haircut(): void; 3} 4 5class Man{ 6 name: string; 7} 8let imgss = new Man(); 9 10enum Color {red, blue, yellow} 11 12interface dogfood { 13 14 brand: string; 15 price: number 16} 17type event = 'mouse' | 'keyboard'; 18 19function foo(){} 20 21let a = 2; 22var b = {}; 23const c = null; 24
namespace用来声明一个命名空间,比较著名的命名空间有lodash,里面有一堆工具函数,统统放在一个叫_的namespace里面,同时你也可以let $ = _;所以namespace也声明了一个值。
class声明了一个值,也声明了一种类型,你可以把Man赋值给一个变量,所以class是一种值,也可以说imgss是一个Man(类型),此时Man承担了一种类型的角色。
enum声明了一个值,也声明了一种类型。我们说red是一种Color,Color在这里承担类型的角色,也可以把Color赋值给一个变量
interface声明了一种类型,但是你不能把dogfood赋值给某个变量,否则你会得到一个报错``dogfood' only refers to a type, but is being used as a value here`
其他function,let,var,const都在声明一个值,你 不能说xxx是一个a,或者xxx是一个foo,不能把值当成类型使用。
2. interface和class
我们知道,不算symbol,js中有6种基本类型,number,string,boolean,null, undefined, object。但是只依靠这几种类型,来描述某个函数需要传什么样的参数,是远远不够的,这也是interface的使命--描述一个值(value)的形状(type)。
现在我们来看class,class首先也具有interface的能力,描述一个形状,或者说代表一种类型。此外class还提供了实现,也就是说可以被实例化;
所以class可以implements interface:
1interface ManLike { 2 speak(): void; 3 leg: number; 4 hand: number; 5} 6class Human implements ManLike { 7 leg: number = 2; 8 hand: number = 2; 9 speak() { 10 console.log('i can speak'); 11 } 12}
而interface可以extends class,此时的class承担类型的角色
1interface Chinese extends Human { 2 country: string; 3}
那么interface能不能extends enum或者type alias呢,这两个兄弟也声明了type啊,答案是不行的,官方报错的信息:
An interface can only extend an object type or intersection of object types with statically known members.
3. class和abstract class
class和abstract class的区别主要是abstract class不能被实例化:
1abstract Human { 2 name: string; 3 abstract lang(): void; 4 toString() { 5 return `<human:${this.name}>` 6 } 7} 8new Human // Cannot create an instance of an abstract class.
4. interface和abstract class
两者都不能被实例化,但是abstract class 也可以被赋值给变量。
interface 里面不能有方法的实现,abstract class 可以提供部分的方法实现,这些方法可以被子类调用。