ts从入门到进阶—4.1类
发布日期:2021-05-06 19:34:52 浏览次数:26 分类:精选文章

本文共 5030 字,大约阅读时间需要 16 分钟。

1.类

  • 我们声明一个 Greeter类。这个类有3个成员:一个叫做 greeting的属性,一个构造函数和一个 greet方法。
  • 我们在引用任何一个类成员的时候都用了 this。 它表示我们访问的是类的成员。
  • 我们使用 new构造了 Greeter类的一个实例。 它会调用之前定义的构造函数,创建一个 Greeter类型的新对象,并执行构造函数初始化它。
class Greeter {    greeting: string;    constructor(message: string) {        this.greeting = message;    }    greet() {        return "Hello, " + this.greeting;    }}let greeter = new Greeter("world");

 2.继承

  • 继承就是类从基类中继承了属性和方法。
  • Dog是一个 派生类,它派生自 Animal 基类,通过 extends关键字。 派生类通常被称作 子类,基类通常被称作 超类
  • 因为 Dog继承了 Animal的功能,因此我们可以创建一个 Dog的实例,它能够 bark()和 move()

class Animal {    move(distanceInMeters: number = 0) {        console.log(`Animal moved ${distanceInMeters}m.`);    }}class Dog extends Animal {    bark() {        console.log('Woof! Woof!');    }}const dog = new Dog();dog.bark();dog.move(10);dog.bark();

 

class Animal {    name: string;    constructor(theName: string) { this.name = theName; }    move(distanceInMeters: number = 0) {        console.log(this);        console.log(`${this.name} moved ${distanceInMeters}m.`);    }}class Snake extends Animal {    constructor(name: string) { super(name); }    move(distanceInMeters = 5) {        console.log("Slithering...");        super.move(distanceInMeters);    }}class Horse extends Animal {    constructor(name: string) { super(name); }    move(distanceInMeters = 45) {        console.log("Galloping...");        super.move(distanceInMeters);    }}let sam = new Snake("Sammy the Python");let tom: Animal = new Horse("Tommy the Palomino");sam.move();tom.move(34);

在控制台上面执行

//test.ts上面的文件tsc test.tstsc test.js

 打印

可以看到

此外还有几点需要注意

  •  在派生类的构造函数(constructor)里面访问this的属性之前必须调用super()(作用是执行基类的构造函数)
  • 可以在子类里面重写父类的方法。move()
  • 即使 tom被声明为 Animal类型,但因为它的值是 Horse,调用 tom.move(34)时,它会调用 Horse里重写的方法

3.公共,私有与受保护的修饰符

默认为 public 

在TypeScript里,成员都默认为 public

理解 private

当成员被标记成 private时,它就不能在声明它的类的外部访问。比如:Aniaml.name也不行。只能类的内部访问

class Animal {    private name: string;    constructor(theName: string) { this.name = theName; }}new Animal("Cat").name; // 错误: 'name' 是私有的.

理解 protected

  • protected修饰符与 private修饰符的行为很相似,但有一点不同, protected成员在派生类中仍然可以访问。例如getElevatorPitch方法中的${this.name}
  • 我们不能在 Person类外使用 name,但是我们仍然可以通过 Employee类的实例方法访问,因为 Employee是由 Person派生而来的。
class Person {    protected name: string;    constructor(name: string) { this.name = name; }}class Employee extends Person {    private department: string;    constructor(name: string, department: string) {        super(name)        this.department = department;    }    public getElevatorPitch() {        return `Hello, my name is ${this.name} and I work in ${this.department}.`;    }}let per = new Person('tes');// per.name; //错误  属性“name”受保护,只能在类“Person”及其子类中访问。// Person.name;//错误   编译无法通过Property 'name' does not exist on type 'typeof Person'.let howard = new Employee("Howard", "Sales");console.log(howard.getElevatorPitch());// console.log(howard.name); // 错误   属性“name”受保护,只能在类“Person”及其子类中访问。

  • 构造函数也可以被标记成 protected。 这意味着这个类不能在包含它的类外被实例化,但是能被继承。比如,
class Person {    protected name: string;    protected constructor(theName: string) { this.name = theName; }}// Employee 能够继承 Personclass Employee extends Person {    private department: string;    constructor(name: string, department: string) {        super(name);        this.department = department;    }    public getElevatorPitch() {        return `Hello, my name is ${this.name} and I work in ${this.department}.`;    }}let howard = new Employee("Howard", "Sales");let john = new Person("John"); // 错误: 'Person' 的构造函数是被保护的.

 4.readonly修饰符

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

class Octopus {    readonly name: string;    readonly numberOfLegs: number = 8;    constructor (theName: string) {        this.name = theName;    }}let dad = new Octopus("Man with the 8 strong legs");dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.

参数属性

适用情况(我们必须在Octopus类里定义一个只读成员 name和一个参数为 theName的构造函数,并且立刻将 theName的值赋给 name,这种情况经常会遇到。

看下面将声明和赋值合并到一处,和上面的代码效果是一样的(当然此处的readonly换成priavte,public等都是可以的)

class Octopus {    readonly numberOfLegs: number = 8;    constructor(readonly name: string) {    }}

5.存取器

TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。

首先看下面例子

class Employee {    fullName: string;}let employee = new Employee();employee.fullName = "Bob Smith";if (employee.fullName) {    console.log(employee.fullName);}

我们现在对上面的例子进行改写

let passcode = "secret passcode";class Employee {    private _fullName: string;    get fullName(): string {        return this._fullName;    }    set fullName(newName: string) {        if (passcode && passcode == "secret passcode") {            this._fullName = newName;        }        else {            console.log("Error: Unauthorized update of employee!");        }    }}let employee = new Employee();employee.fullName = "Bob Smith";if (employee.fullName) {    alert(employee.fullName);}
  • 我们先检查用户密码是否正确,然后再允许其修改员工信息
  • 我们可以修改一下密码,来验证一下存取器是否是工作的。当密码不对时,会提示我们没有权限去修改员工。

以下需要注意

  • 首先,存取器要求你将编译器设置为输出ECMAScript 5或更高。 不支持降级到ECMAScript 3。所以在编译的时候可以这样写node test.ts --target es6
  • 只带有 get不带有 set的存取器自动被推断为 readonly。 这在从代码生成 .d.ts文件时是有帮助的,因为利用这个属性的用户会看到不允许够改变它的值。

 

 

上一篇:ts从入门到进阶—4.2类
下一篇:ts从入门到进阶—3-9接口(二)

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2025年03月27日 16时28分22秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章