前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >typescript基础篇(5):类

typescript基础篇(5):类

作者头像
一粒小麦
发布2020-08-12 10:53:15
6450
发布2020-08-12 10:53:15
举报
文章被收录于专栏:一Li小麦

5.类

5.1 类的声明与继承

ts的类基本包括了es6+中类的全部功能。假如我要声明一条“狗”类,在ts中实现一个类是这样的:

代码语言:javascript
复制
class Dog {
  constructor(name: string) {
    this.name = name
  }
  name: string
  run() {
    console.log(`${this.name} is running`)
  }
}

const dog = new Dog("Bobby")

类属性都是实例属性,而不是原型属性。ts中属性必须被初始化

如果为狗类声明一个子类(哈士奇类),并且有哈士奇有它的属性:颜色:

代码语言:javascript
复制
class Hasky extends Dog {
  constructor(name: string, color: string) {
    super(name)
    this.color = color
  }

  color: string
}

const hasky = new Hasky("haha", "white")
hasky.run() // haha is running
console.log(hasky.color) // white

5.2 修饰符

5.2.1 public

类所有默认的修饰符都是public。表示作用域内所有成员可见。如:

代码语言:javascript
复制
class Dog {
  constructor(name: string) {
    this.name = name
  }
  public name: string // 类型注解
  run() {
    console.log(`${this.name} is running`)
  }
}

可以不写。在构造函数的参数上使用public等同于创建了同名的成员变量。

5.2.2 private

表示为一个类的私有成员,只有类本身内部可以调用,子类和实例无法调用:

代码语言:javascript
复制
class Dog {
  constructor(name: string) {
    this.name = name
  }
  public name: string // 类型注解

  // 私有成员
  private eat() {
    console.log(`dog is eating`)
  }
  run() {
    console.log(`${this.name} is running`)
  }
}

如果private修饰constructor,表示这个类既不能被实例化,也不能被继承。

5.2.3 protected

Protected修饰需要保护的成员——只能在类和子类中访问,但不能在它们的实例中访问

如果protected修饰的contructor,那么表示它不能被实例化,而只能被继承。也就是所谓的“基类”。

5.2.4 readonly

只读属性。不可以被修改,必须在属性中被实例化。

5.2.5 修饰参数

修饰符也可以用于修饰参数。比如我在参数重直接public color,就不必再申明了,构造函数的写法都可以不写了。

代码语言:javascript
复制
class Hasky extends Dog {
  constructor(name: string, public color: string) {
    super(name)
  }
}
5.2.6 static

静态成员只能通过类名来调用,可以被继承。

代码语言:javascript
复制
class Dog {
  constructor(name: string) {
    this.name = name
  }
  public name: string // 类型注解
  private eat() {
    console.log(`dog is eating`)
  }
  protected sleep() {}
  static food: string = "aaa"
  run() {
    console.log(`${this.name} is running`)
  }
}

5.3 抽象类与多态

ts的抽象类是对js的又一扩展。如果做这么一个类比:有一个“动物”类,它抽象概括了大部分生物的特征,但它没法被实例化,只有通过”狗“类,“人”类等子类来使之形象化。

因而,可以说抽象类是只能被继承但不能实例化的类。在ts中,通过abstract来声明抽象类。

代码语言:javascript
复制
abstract class Animal {
  constructor() {}

  shout() {
    console.log("shout")
  }
}

class Dog extends Animal {
  constructor(public name: string) {
    super()
  }
  run() {
    console.log(`${this.name} is running`)
  }
}

const dog = new Dog("Bobby")
dog.shout()

抽象类中,也可以不指定方法等具体实现,这就构成了抽象方法。子类有此实现,就没必要在在父类中实现了。

代码语言:javascript
复制
abstract class Animal {
  constructor() {}

  abstract shout(): void
}

class Cat extends Animal {
  constructor() {
    super()
  }
  shout() {
    console.log("miao")
  }
}

class Dog extends Animal {
  constructor() {
    super()
  }

  shout() {
    console.log("wang")
  }
}

const animals: Animal[] = [new Cat(), new Dog()]
animals.forEach((animal) => {
  animal.shout()
})// miao wang

上面的例子中,给Animal定义了一个shout方法。但是具体的实现交给了子类来完成。从这个意义来说,模板方法模式的思想很好地得到了实现。

不单类可以多态,this也可以多态。我想在ts中实现类似jquery的链式调用。和js写法一致,思路依然是在原型方法中return this

代码语言:javascript
复制
class WorkFlow {
  step1() {
    return this
  }

  step2() {
    return this
  }
}

new WorkFlow().step1().step2()

如果在子类中这么做,this可以同时调用子类和父类的方法:

代码语言:javascript
复制
class MyFlow extends WorkFlow {
  next() {
    return this
  }
}

new MyFlow().step1().next().step2()

5.4 类与接口的关系

实现(implements)是面向对象中的一个重要概念。一般来讲,一个类只能继承自另一个类,有时候不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口(interfaces),用 implements 关键字来实现。这个特性大大提高了面向对象的灵活性。

举例来说,门是一个类,防盗门是门的子类。如果防盗门有一个报警器的功能,我们可以简单的给防盗门添加一个报警方法。这时候如果有另一个类,车,也有报警器的功能,就可以考虑把报警器提取出来,作为一个接口,防盗门和车都去实现它。

通过接口,可以约束类成员有哪些属性,还有哪些类型。比如说,我先定义一个“人”类,包括name属性(string),和eat方法(void)。然后通过implements关键字,按照这个接口去实现“亚洲人”类。

代码语言:javascript
复制
interface Human {
  name: string
  eat(): void
}

class Asian implements Human {
  constructor(public name: string) {}
  eat() {}
}

注意,类必须要完整声明完接口声明的成员(公有成员,不可改动)。如果类有自己的属性,这是可以的。也不能在接口定义构造函数。

5.4.1 接口之间的继承
代码语言:javascript
复制
interface Human {
  name: string
  eat(): void
}

class Asian implements Human {
  constructor(public name: string) {}
  eat() {}
}

interface American extends Human {
  run(): void
}

interface European extends Human {
  cry(): void
}

interface African extends American, European {}

// 必须完整定义完父接口的方法
const p: African = {
  name: "",
  run() {},
  cry() {},
  eat() {},
}

这里p实际上也是被编译为一个对象。

5.4.2 接口与类之间的继承

接口继承类,然后再用一个类来继承这个接口:

代码语言:javascript
复制
class Auto {
  state = 1
}

interface AutoInterface extends Auto {}

class C implements AutoInterface {
  state = 1 
}

在此,如果C不定义state,将会报错。

下图反映了接口和类的关系:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一Li小麦 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 5.类
    • 5.1 类的声明与继承
      • 5.2 修饰符
        • 5.2.1 public
        • 5.2.2 private
        • 5.2.3 protected
        • 5.2.4 readonly
        • 5.2.5 修饰参数
        • 5.2.6 static
      • 5.3 抽象类与多态
        • 5.4 类与接口的关系
          • 5.4.1 接口之间的继承
          • 5.4.2 接口与类之间的继承
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档