定义类
在 TypeScript 中,我们也是通过 Class 关键字来定义一个类, 使用 constructor 定义构造函数。
class Animal {
public name: string;
constructor(name: string) {
this.name = name;
}
sayHi(): string {
return `我的名字 ${this.name}`;
}
}
继承
TS中的继承ES6中的类的继承极其相似,子类可以通过extends关键字继承一个类 例如
在构造器里访问 this 的属性之前,一定要调用 super() ,这个是 TypeScript 强制执行的一条重要规则。
class Person {
constructor (name) {
// 等价于我们的构造函数体
this.name = name
}
// 原型上的方法
sayHi () {
console.log('hello world')
}
}
// 2. 准备一个子类
// 一个继承自 Person 的 Student 子类
class Student extends Person {
constructor (age, name) {
// super(name) // 就相当于我们 es5 的借用构造函数继承
// 只不过不需要我们写 call 去改变 this 指向了
// 直接帮我们改变好 this 指向了, 我们只需要传递参数就可以了
super(name)
this.age = age
}
son () {
console.log('我是 子类的方法')
}
}
var s1 = new Student(18, 'Jack')
console.log(s1)
跟ES6一样,子类构造函数必须加上super()执行父类的构造constructor函数
所以,大家常常说,一个子类实例,同时也是父类的实例
类的修饰符
TypeScript 中有三类访问修饰符,分别是: public、private、protected。不写默认为 public
public:自己、自己的子类 和其他类都可以访问 (默认值)protected:受保护的 自己和自己的子类能访问, 其他类不能访问private:私有的 只能自己访问,自己的子类不能访问,其他类更不能访问
// 定义一个类
class Person {
// name:string
// private name:string
protected name:string
constructor(name:string){
this.name = name
}
public eat(){
console.log(`${this.name},好吃`)
}
}
// 定义一个子类
class Student extends Person {
constructor(name:string){
super(name)
}
play(){
// 当name为protected时,子类中也可访问;
// 但如果其为private,子类中则无法访问
console.log('like play',this.name)
}
}
const p1 = new Person('张三')
// console.log(per.name) // name 为私有,外部无法访问
per.eat()
定义接口
接口的作用类似于抽象类,不同点在于接口中的所有方法和属性都是没有实值的,换句话说接口中的所有方法都是抽象方法。接口主要负责定义一个类的结构,接口可以去限制一个对象的接口,对象只有包含接口中定义的所有属性和方法时才能匹配接口。同时,可以让一个类去实现接口,实现接口时类中要保护接口中的所有属性。
// 定义接口
class Person {
name: string;
age: number;
}
interface Man extends Person {
money: string;
}
let me: Man = {
name: 'funlee',
age: 18,
money: '100W'
}
枚举
使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字Number的和基于字符串String的枚举。
数字枚举
enum Direction {
Up = 1,
Down,
Left,
Right
}
如上,我们定义了一个数字枚举, Up使用初始化为 1。 其余的成员会从 1开始自动增长。 换句话说, Direction.Up的值为 1, Down为 2, Left为 3, Right为 4。
我们还可以完全不使用初始化器:
enum Direction {
Up,
Down,
Left,
Right,
}
现在, Up的值为 0, Down的值为 1等等。 当我们不在乎成员的值的时候,这种自增长的行为是很有用处的,但是要注意每个枚举成员的值都是不同的。
字符串枚举
字符串枚举的概念很简单,但是有细微的 运行时的差别。 在一个字符串枚举里,每个成员都必须用字符串字面量,或另外一个字符串枚举成员进行初始化。
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
由于字符串枚举没有自增长的行为,字符串枚举可以很好的序列化。 换句话说,如果你正在调试并且必须要读一个数字枚举的运行时的值,这个值通常是很难读的 - 它并不能表达有用的信息(尽管 反向映射会有所帮助),字符串枚举允许你提供一个运行时有意义的并且可读的值,独立于枚举成员的名字。