typescript中的类

typescript 中的类与 es6 中的类在使用上基本一样,举个小例子:

class Person{
  name:string;
  constructor(name:string){
    this.name = name
  }
  sayHi(){
    console.log('hi')
  }
}

// 定义 Teacher 继承 Person
class Teacher extends Person{
  constructor(name:string){
    super(name)
  }
  teach(){
    console.log('teach')
  }
}

const teacher = new Teacher('Tom')
console.log(teacher.name) // Tom
teacher.sayHi() // hi
teacher.teach() // teach

 

例子中实现了类的基本定义以及类的继承。如果了解 es6 的话,理解起来不难,需要注意的是 typescript 中强制你在派生类的构造函数中必须调用 super(),即在构造函数里访问 this 的属性之前,我们一定要调用 super(),它执行基类的构造函数。

基类是指父类,也被叫做“超类”,派生类则是子类。

 

修饰符

typescript 中为类提供了四个修饰符,分别是 public(公共的)、private(私有的)和 protected(受保护的),还有一个 readonly(只读)。

 

public

默认情况下 typescript 中定义的属性和方法都是公共的,即可以在类的外部访问到。有时 TSLint 可能会要求你必须用修饰符来表明这个属性或方法是什么类型的,手动添加即可,如下:

class Point{
  public x:number;
  public y:number;

  constructor(x:number,y:number){
    this.x = x
    this.y = y
  }

  public getPosition(){
    return `${this.x}:${this.y}`
  }
}

 

private

当成员被标记成 private时,它就不能在声明它的类的外部访问。比如:

class Animal{
  private name:string;

  constructor(name:string){
    this.name = name
  }

  getName(){
    console.log(this.name)
  }
}

const cat = new Animal('cat')

console.log(cat.name) // Property 'name' is private and only accessible within class 'Animal'.

cat.getName() // cat

 

protected 

protected 与 private 类似,区别在于被 protected 标记的属性可以在子类中访问到,而 private 标记的属性不能在子类中访问到。

class Person{
  protected name:string;

  constructor(name:string){
    this.name = name
  }
}

class Student extends Person{
  private age:number;

  constructor(name:string,age:number){
    super(name)
    this.age = age
  }

  getName(){
    console.log(this.name)
  }
}

const s = new Student('小明',18)

s.getName() // 小明

console.log(s.name) // 属性 “name” 受保护,只能在类 “Person”及其子类中访问

 

上述例子中,name 属性可以在子类 Student 中获取,但是在类的外部就获取不到了。

 

protected 还可以标记构造函数,意味着这个被标记的类不能被实例化,只能继承:

class Person{
  protected constructor(){
    
  }
}

const p = new Person() // 类 “Person” 的构造函数是受保护的,仅可在类声明中访问

class Student extends Person{
  constructor(){
    super()
  }
}

const s = new Student()

 

readonly

使用 readonly 关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。

class UserInfo{
  readonly name:string;

  constructor(name:string){
    this.name = name
  }
}

const user = new UserInfo('Tom')

user.name = 'Bob' // Cannot assign to 'name' because it is a read-only property

 

参数属性

参数属性可以用来简化一个过程。什么过程?就拿上面的例子来说,我们在 UserInfo 类里,定义一个只读属性 readonly 和一个参数为 name 的构造函数,然后要在构造函数中进行 this.name = name 的赋值,这种操作是经常遇到的,利用参数属性我们可以简化这个过程,变成如下这样:

class UserInfo{
  constructor(readonly name:string){}
}

const user = new UserInfo('Tom')
console.log(user.name) // Tom

现在仅在构造函数里使用 readonly name: string 参数来创建和初始化 name成员,把声明和赋值合并至一处了。

 

参数属性简单来说就是在 constructor 构造函数的参数前面加上访问限定符,也就是前面说的 public、private、protected 和 readonly 中的任意一个。
 

静态属性 

在 TS 中使用 static 关键字来指定属性或方法是静态的,实例不会添加这个静态属性,也不会继承静态方法。

class Car{
  static color:string = 'red';
  getColor(){
    console.log(Car.color)
  }
  constructor(){
    // 
  }
}

const p = new Car()
console.log(p.color) // Property 'color' is a static member of type 'Car'
p.getColor() // red

 

可选属性

使用 ? 符号来标记可选属性:

class Info{
  name:string;
  age?:number;

  constructor(name:string,age?:number,sex?:string){
    this.name = name
    this.age = age
  }
}

const info1 = new Info('A')
const info2 = new Info('B',18)
const info3 = new Info('C',18,'man')

 

存取器

存取器即是存值函数和取值函数,也就是在设置属性值的时候调用的函数,和在访问属性值的时候调用的函数,使用关键词 get 和 set。

class Info{
  private _name:string;

  get name(){
    // 在获取值前,可以做一些判断操作
    return this._name
  }

  set name(value){
    // 在设置值前,可以做一些判断操作
    this._name = value
  }

  constructor(){
    //
  }
}

const info = new Info()
info.name = 'Tom'
console.log(info.name) // Tom

 

抽象类

抽象类用来被其他类继承,而不能被实例化,使用 abstract 关键字定义抽象类和在抽象类内部定义抽象方法。

abstract class People{
  name:string
  constructor(name:string){this.name = name}
  abstract printName():void
}

class Man extends People{
  constructor(name:string){
    super(name)
  }
  // 抽象方法无法从父类继承,需要自己实现
  printName(){
    console.log(this.name)
  }
}

const m = new Man('Tom')
m.printName() // Tom

const p = new People() // 无法创建抽象类的实例

 

abstract 关键字也可以定义抽象属性和抽象存取器:

abstract class People{
  abstract name:string
  abstract printName():void
  abstract get insideName():string
  abstract set insideName(value:string)
  
  constructor(name:string){}
}

 

 

 

 

posted @ 2020-05-03 09:49  黑色瓶子  阅读(324)  评论(0编辑  收藏  举报