【TypeScript】类

1、定义类

定义类的示例:

class Person {
    name: string;

    constructor(name: string) { // 构造函数,实例化类的时候触发的方法
        this.name = name;
    }

    getName(): string {
        return this.name;
    }
    setName(name: string): void {
        this.name = name;
    }
}

let per = new Person('xiaoming');

2、类的继承

  • 继承是一种oop(面向对象编程)的概念,它允许一个类继承另一个类的属性和方法
  • 关键字:extends

2.1 基本的继承:

class Animal {
    move(distance: number) {
        console.log('跑了' + distance + '米');
    }
}
class Dog extends Animal {
    bark() {
        console.log('Woof! Woof!');
    }
}

const dog = new Dog();
dog.bark(); // Woof! Woof!
dog.move(10); // 跑了10米

这个例子展示了最基本的继承:类从基类中继承了属性和方法。

这里, Dog是一个 派生类,它派生自 Animal 基类,通过 extends关键字。

派生类通常被称作 子类,基类通常被称作 超类

2.2 包含构造函数的继承

  • 派生类包含了一个构造函数,它 必须调用 super(),它会执行基类的构造函数
  • 在构造函数里访问 this的属性之前,一定要调用 super()
    // 父类
    class Animal {
        name: string;
    
        constructor(name: string) {
            this.name = name;
        }
    
        move(distance: number) {
            console.log(this.name + '跑了' + distance + '米');
        }
    }
    
    // 使用 extends 关键字创建了 Animal的子类:Dog。
    class Dog extends Animal {
        constructor(name: string) { 
            super(name); // 必须调用 super()
        }	
    	
    	// 子类里可以重写父类的方法
        move(distance: number = 5) { 
            console.log("Woofing...");
            super.move(distance);
        }
    }
    
    // 使用 extends关键字创建了 Animal的子类:Snake。
    class Snake extends Animal {
        constructor(name: string) {
            super(name); // 必须调用 super()
        }
        // 子类里可以重写父类的方法
        move(distanceInMeters = 45) {
            console.log("Slithering...");
            super.move(distanceInMeters);
        }
    }
    
    const dog = new Dog('二哈');
    dog.move(10);
    const snake = new Snake('蛇');
    snake.move();
    

3、修饰符

3.1 public

在TypeScript里,类的成员都默认为 public

class Animal {
    public name: string;
    public constructor(theName: string) { this.name = theName; }
    public move(distanceInMeters: number) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}

3.2 private

当成员被标记成 private时,它就不能在声明它的类的外部访问,派生类也无法访问

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName }
    
    run() {
        console.log(this.name + '在叫'); // 允许
    }
}

let dog = new Animal("dog");
dog.name; // 错误: 'name' 是私有的
dog.run() // 打印‘dog在叫’

子类中也不能访问该属性

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

class Dog extends Animal {
    constructor(theName: string) {
        super(theName);
    }
    run() {
        console.log(this.name + '在叫'); // 错误
    }
}

3.3 protected

protected修饰符与 private修饰符的行为很相似,不同的是protected成员在派生类中仍然可以访问。
注意:我们不能在 Animal类外使用 name,但是我们仍然可以通过 Dog类的实例方法访问

class Animal {
    protected name: string;
    constructor(theName: string) { this.name = theName; }
}

class Dog extends Animal {
    constructor(theName: string) {
        super(theName);
    }
    run() {
        console.log(this.name + '在叫'); // 派生类中可以访问
    }
}

let dog = new Dog('dog');
dog.run();
console.log(dog.name); // 错误(name不能在类外访问,只能通过实例方法去访问)

3.4 readonly

  • 使用 readonly关键字将属性设置为只读的
  • 只读属性必须在声明时或构造函数里被初始化
class Person {
    readonly name: string;
    constructor(theName: string) {
        this.name = theName;
    }
}
let xiaoming = new Person('xiaoming');
xiaoming.name = 'xiaohong' // 错误! name 是只读的.

3、存取器

TypeScript 支持通过 getters/setters 来截取对对象成员的访问
注意:

  • 存取器要求你将编译器设置为输出ECMAScript 5或更高
  • 只带有 get不带有 set的存取器自动被推断为 readonly
// 我们先检查用户密码是否正确,然后再允许其修改员工信息

let passcode = "secret passcode";

class Employee {
    private _fullName: string;
    constructor(theName: string) {
        this._fullName = theName;
    }

    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');
employee.fullName = "Bob Smith";
console.log(employee.fullName);

4、静态属性

  • 关键字: static
  • 静态属性存在于类本身上面,而不是类的实例上
  • 只能通过类名来访问静态属性
class Person {
    static age = 24;
    
    sayAge() {
        return Person.age; // 通过类名访问
    }
}
let p = new Person();
console.log(p.sayAge()); // 24
console.log(Person.age); // 24 通过类名访问

5、抽象类

  • 所谓抽象类,是指只能被继承,但不能被实例化的类
  • 抽象类两个特点:
    • 抽象类不允许被实例化
    • 抽象类中的抽象方法必须被子类实现
  • 不同于接口,抽象类可以包含成员的实现细节
  • abstract 关键字是用于定义抽象类和在抽象类内部定义抽象方法
abstract class Animal { // 定义抽象类
    abstract makeSound(): void; // 定义抽象方法
    move(): void { // 抽象类可以包含成员的实现细节
        console.log('roaming the earch...');
    }
}

抽象类中的抽象方法不包含具体实现,并且必须在派生类中实现

// 定义抽象类
abstract class Department {
    constructor(public name: string) {
    }

    abstract printMeeting(): void; // 必须在派生类中实现
}

// 派生类
class Account extends Department {
    constructor() {
        super('Account') // 在派生类的构造函数中必须调用 super()
    }

    printMeeting(): void {
        console.log('Account printMeeting...');
    }
}

let department: Department; // 允许创建一个对抽象类型的引用
department = new Department() // 错误: 不能创建一个抽象类的实例

department = new Account(); // 允许对一个抽象子类进行实例化和赋值
department.printMeeting();

6、高级技巧

6.1 构造函数

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

let greeter: Greeter;
greeter = new Greeter("world");
console.log(greeter.greet());

编译成 JavaScript

let Greeter = (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    return Greeter;
})();

let greeter;
greeter = new Greeter("world");
console.log(greeter.greet());

6.2 把类当做接口使用

因为类可以创建出类型,所以你能够在允许使用接口的地方使用类

class Point {
    x: number | undefined;
    y: number | undefined;
}

interface Point3d extends Point {
    z: number;
}

let point3d: Point3d = { x: 1, y: 2, z: 3 };
console.log(point3d);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值