TypeScript:类的构造函数和修饰符

2,390 阅读3分钟

「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

前言

从ECMAScript 2015,也就是ECMAScript 6开始,JavaScript程序员将能够使用基于类的面向对象的方式。而TypeScript增强了类的相关语法。

构造函数

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

其实这里是会报错的:Property 'name' does not exist on type 'Person'.这里就需要我们在Person中标明name属性

class Person { 
    name: string // 'init name'
    age: number
    constructor(name: string, age: number) { 
        this.name = name
        this.age = age
    }
}

总而言之我们的类属性就需要先进行标明值的属性

修饰符

访问修饰符私有属性和共有属性,相信学过Java的同学都会知道 在TypeScript里,成员都默认为 public。当然你也可以明确的将一个成员标记成 public。

public

直接来个例子:

class Person {
    public height: number;
    public constructor(theHeight: string) { 
        this.height = theHeight; 
    }
    public move(distanceInMeters: number) {
        console.log(`这个人的身高是${height}cm`);
    }
}

private 私有化

还是继续使用之前的Person类,我们为其添加私有类weight

class Person {
    public height: number;
    private weight: number;
    public constructor(tHeight: number, tWeight) { 
        this.height = tHeight; 
        this.weight = tWeight
    }
    public move(distanceInMeters: number) {
        console.log(`这个人的身高是${this.height}cm, 体重是${this.weight}kg`);
    }
}

大家有的人不了解这个的会很好奇,私有类有什么特别的呢???

这里我们给大家举两个例子就知道了

1.继承

class Person {
  public height: number;
  private weight: number;
  public constructor(tHeight: number, tWeight) {
    this.height = tHeight;
    this.weight = tWeight;
  }
  public move() {
    console.log(`这个人的身高是${this.height}cm, 体重是${this.weight}kg`);
  }
}
class Woman extends Person {
  constructor() { 
    super(100, 100) // 在派生类的构造函数中必须调用 super()
  }
  addWeight() { 
    this.weight = this.weight + 10
  }
  addHeight() { 
    this.height = this.height + 10
  }
}

这里我们创建了一个Woman类继承了父类Person,并实现了两个方法addWeightaddHeight,但是请看下图:

image.png 这里我们可以看见,我们在继承了Person之后,公有的成员height是可以进行访问的,而私有成员weight访问就报错了

2.实例化

let a = new Person(100, 100);
a.height = 100
a.weight = 10;

image.png 这里我们可以看见,我们在实例化了Person之后,公有的成员height是可以进行访问的,而私有成员weight访问就报错了

private(私有修饰符) 小结

根据两个例子:公有的成员height是可以进行访问的,而私有成员weight访问就报错了的情况,所以我们可以得出结论 当成员被标记成 private时,它就不能在声明它的类的外部访问。

protected 修饰符

protected修饰符与 private修饰符的行为很相似,但有一点不同, protected成员在派生类中仍然可以访问。但是在实例化中依然不能访问

class Person {
  public height: number;
  private weight: number;
  protected age: number;
  public constructor(tHeight: number, tWeight) {
    this.height = tHeight;
    this.weight = tWeight;
    this.age = 18 // 永远的18岁!!!
  }
  public move() {
    console.log(`这个人的身高是${this.height}cm, 体重是${this.weight}kg`);
  }
}
class Woman extends Person {
  constructor() {
    super(100, 100);
  }
  showAge() {
    console.log(this.age)
  }
  addHeight() {
    this.height = this.height + 10;
  }
}
let g = new Person(180, 75)
g.age = 19

image.png 说的没错吧亲!

readonly自读修饰符

只读属性必须在声明时或构造函数里被初始化。也就是说只能在构造函数中进行赋值的操作,其他地方就会出现报错的情况:

类中非构造函数

class Person {
  readonly name: string;
  public constructor() {
    this.name = '-'
  }
  public name() {
    this.name = '--'
  }
}

image.png

子类中

class Woman extends Person {
  constructor() {
    super();
    this.name = '---'
  }
  changeName() {
    this.name = 1
  }
}

image.png

实例化

image.png

使用修饰符对构造函数进行声明

如果我们使用修饰符对构造函数进行赋值的话,会出现无法继承,无法被实例化的情况(构造函数默认为public)假设我们做出了如下的操作

  • 构造函数 设置为private

     class Person {
          private constructor() {
            console.log(1)
          }
        }
    
    • 继承失败了

      class Woman extends Person {
        constructor() {
          super();
        }
      }
      

    就会出现无法继承的情况,报错如图: image.png

    • 实例化失败了

      let g = new Person()
      

      就会出现无法实例化的情况,报错如图:

image.png

  • 构造函数 设置protected

    class Person {
      protected constructor() {
        console.log(1)
      }
    }
    
    • 继承 是可以正常 继承的

      class Woman extends Person {
        constructor() {
          super();
        }
      }
      

    image.png

    • 实例化失败了
      let g = new Person()
      ```
      
    

image.png

  • 构造函数设置 readonly 直接报错了亲!

image.png

抽象类

抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。 abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。

抽象类书写:

abstract class Person {
    abstract ask(): void; // // 必须在派生类中实现
    run(): void {
        console.log('跑起来,点赞,评论,一键三连');
    }
}

抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。 抽象方法的语法与接口方法相似。 两者都是定义方法签名但不包含方法体。 然而,抽象方法必须包含 abstract关键字并且可以包含访问修饰符。

实例化抽象类

let g = new Person()

image.png

继承抽象类

如果不实现抽象类中的抽象成员

class Woman extends Person {
  
}

image.png

总结

本章,我们遇到了类的构造函数、修饰符已经抽象类,也知道了个个修饰符对构造函数的作用以及影响,还有抽象类的用法,看到这里了,点个赞再走吧!

求赞.jpeg