TypeScript 笔记(三、类和接口)

作为一个面向对象的语言,类和接口不可或缺,相比现行的JavaScript,这两个概念都是新引入的,本文将对这两个概念进行详细介绍。

1. 什么是类

传统方法中,JavaScript通过构造函数实现类的概念,通过原型链实现继承。而在ES6中,我们终于迎来了class。

  • 类(Class):定义了一件事物的抽象特点,包含它的属性和方法
  • 对象(Object):类的实例,通过 new 生成
  • 面向对象(OOP)的三大特性:封装、继承、多态
  • 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,同时也保证了外界无法任意更改对象内部的数据
  • 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性
  • 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。比如 Cat 和 Dog 都继承自 Animal,但是分别实现了自己的 eat 方法。此时针对某一个实例,我们无需了解它是 Cat 还是 Dog,就可以直接调用 eat 方法,程序会自动判断出来应该如何执行 eat
  • 存取器(getter & setter):用以改变属性的读取和赋值行为
  • 修饰符(Modifiers):修饰符是一些关键字,用于限定成员或类型的性质。比如 public 表示公有属性或方法
  • 抽象类(Abstract Class):抽象类是供其他类继承的基类,抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现
  • 接口(Interfaces):不同类之间公有的属性或方法,可以抽象成一个接口。接口可以被类实现(implements)。一个类只能继承自另一个类,但是可以实现多个接口

TypeScript中的class和Java中的class极其相似,学习起来没有任何瓶颈,理解会很快。

2. 类的典型示例及说明

class Person {
    private _name: string;
    constructor(name: string) { this._name = name; }// 1

    get name(): string {// 2
        return this._name;
    }

    set name(value: string) {// 2
        this._name = value;
    }
}

class Employee extends Person {// 3
    public static readonly id: string = "001";// 4
    private department: string;

    constructor(name: string, department: string) {
        super(name);// 5
        this.department = department;
    }

    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}

let employee: Employee = new Employee("张三", "总办");// 6
console.log(employee.getElevatorPitch());
console.log(Employee.id);

对上述代码说明如下:

  1. 使用constructor关键字声明构造方法,创建对象时将自动调用该方法。
  2. 使用getset关键字声明存取器,封装对属性的访问
  3. 使用extends关键字指定继承关系
  4. 使用static readonly组合创建一个不可变的常量
  5. 子类必须显式调用super方法,指向父类构造方法
  6. 使用new关键字创建类对象

3. 接口

TypeScript中的接口是一个非常灵活的概念,大体上它有如下四种使用方式:

  1. 描述实体,即所谓对「对象的形状(Shape)」进行描述
  2. 描述函数类型
  3. 描述那些能够“通过索引得到”的类型
  4. 类类型,是行为的抽象(Java语言中只有这个用法)

3.1 描述对象的形状(Shape)

Java语言中,这个概念通常叫做实体,对应的文件叫实体类

声明形状接口时,可以通过?设置属性为可选;使用readonly设置属性为只读;使用[propName: string]: any;设置属性为任意类型。

interface Person {
    name: string;
    age?: number;
    readonly id: number;
}

let tom: Person = {
    name: 'Tom',
    id: 25
};

接口可以继承类

当接口继承了一个类类型时,它会继承类的成员但不包括其实现。 就好像接口声明了所有类中存在的成员,但并没有提供具体实现一样。
接口同样会继承到类的private和protected成员。 这意味着当你创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)。

3.2 描述函数类型

使用接口表示函数类型,我们需要给接口定义一个调用签名。它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。

//声明,就像一个没有方法体的匿名函数
interface SearchFunc {
  (source: string, subString: string): boolean;
}

//使用声明的接口
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
  let result = source.search(subString);
  return result > -1;
}

3.3 描述那些能够“通过索引得到”的类型

与使用接口描述函数类型差不多,我们也可以描述那些能够“通过索引得到”的类型,比如a[10]或ageMap[“daniel”]。

可索引类型具有一个索引签名,它描述了对象索引的类型,还有相应的索引返回值类型;共有支持两种索引签名:字符串和数字。

//数字索引
interface StringArray {
  [index: number]: string;
}

let myArray: StringArray;
myArray = ["Bob", "Fred"];

let myStr: string = myArray[0];
//字符串索引
interface StringArray {
    [index: string]: any
    [index: number]: any
    name: string
}

let myArray: StringArray;
myArray = {name:"测试",aa:"aaaa的值",bb:"bbbb的值", 3:11};

let myStr: string = myArray["bb"];
let myName: string = myArray["name"];
let myName3: string = myArray[3];

console.log(myStr);
console.log(myName);
console.log(myName3);

接口描述索引类型时,其作用有点像固定了key类型、value类型的Map,与Java中的Map<?,?>类似。

同时使用number和string类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。

3.4 类类型-实现接口

与C#或Java里接口的基本作用一样,TypeScript也能够用接口来明确的强制一个类去符合某种契约。

interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);
}

class Clock implements ClockInterface {
    currentTime: Date;
    setTime(d: Date) {
        this.currentTime = d;
    }
    constructor(h: number, m: number) { }
}

4. 小结

本文介绍了接口和类的概念,并列举了使用方式。对于类来说,与Java语言非常类似,因此学过Java语言再来看TypeScript中类,会发现基本一模一样。

接口的使用方式列举如下,它与Java语言差异较大,主要是增加了三种新的使用方式(前三种)。

  1. 描述实体,即所谓对「对象的形状(Shape)」进行描述
  2. 描述函数类型
  3. 描述那些能够“通过索引得到”的类型
  4. 类类型,是行为的抽象(Java语言中只有这个用法)

参考的文章

TypeScript 中文手册-类(class)
TypeScript 中文手册-接口(interface)
类 - TypeScript 入门教程
对象的类型——接口 - TypeScript 入门教程
类与接口 - TypeScript 入门教程


文章作者: 沉迷思考的鱼
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 沉迷思考的鱼 !
评论
 上一篇
Mysql 日常脚本记录(不定期更新) Mysql 日常脚本记录(不定期更新)
写一些Mysql脚本时,总会忘记部分具体语法,此时不得不面向浏览器编程,这个体验很糟糕。鉴于此,这里做一个简要的记录,以便快速查看。 查询相邻的两条数据select s1.*, s2.* from ( select t.* from (S
2019-06-08
下一篇 
TypeScript 笔记(二、函数) TypeScript 笔记(二、函数)
函数是JavaScript应用程序的基础,用于定义行为。TypeScript为JavaScript函数添加了额外的功能,让我们可以更容易地使用。 本文将从如下几个方面,介绍TypeScript中的函数。 函数定义 函数的参数 函数重载 t
2019-05-23
  目录