面向对象

类:class

class Person {

    // 静态属性
    static readonly lang: string = "chinese";

    // 静态只读属性,类似const
    static readonly happy: boolean = true;

    // 成员属性/实例属性
    name: string = "孙悟空";

    // 成员属性没有默认值
    age: number;

    // 只读成员属性
    readonly sex: string;

    // 所有属性必须初始化,无论是不是只读属性,而java中只有只读属性(final)才必须初始化
    // 这是构造器,构造器不可以重载
    constructor(age: number, sex: string) {
        this.age = age; // this指代当前对象
        this.sex = sex;
    }

    // 静态方法
    static sayHello() {
        console.log("hello");
    }

    // 成员方法
    printHello() {
        console.log("hello");
    }
}

// 根据类创建对象
const p = new Person(10, "男");
// 访问静态属性
console.log(Person.lang);
// 访问静态方法
Person.sayHello()
// 访问成员属性
console.log(p.age)
// 访问成员方法
p.printHello()

封装

class Person {
    // 下划线是内置命名,但是无法放置其他程序访问
    // 他会与get/set配合
    // private代表私有属性
    private _name: string;
    private _age: number;
    // public代表公开属性
    public happy: boolean = true;
  
  	// 还有一个protected属性,只可以被子类使用
  	// private 不能被子类使用

    constructor(name: string, age: number) {
        this._name = name;
        this._age = age;
    }

    // 提供 getter/setter 获取内部属性,这些方法默认为public的
    get name(): string {
        return this._name;
    }

    set name(value: string) {
        this._name = value;
    }

    get age(): number {
        return this._age;
    }

    set age(value: number) {
        if (value < 0 || value > 120) {
            throw new Error("年龄不能小于0大于120");
        }
        this._age = value;
    }
}

// 通过get/set访问属性
let p: Person = new Person("张三", 18);

// 可以直接通过.的方式访问变量的get/set方法
console.log(p.name); // 访问 _age 的get方法
p.age = -1; // 访问 _name 的set方法

执行结果:

                throw new Error("年龄不能小于0大于120");
                ^

Error: 年龄不能小于0大于120
    at Person.set (/Users/yangsx/Project/temp/nots-ts/src/a.js:25:23)
    at Object.<anonymous> (/Users/yangsx/Project/temp/nots-ts/src/a.js:38:7)
    at Module._compile (node:internal/modules/cjs/loader:1095:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1124:10)
    at Module.load (node:internal/modules/cjs/loader:975:32)
    at Function.Module._load (node:internal/modules/cjs/loader:816:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:79:12)
    at node:internal/main/run_main_module:17:47

解决不可以使用get 和 set的问题:tsc -t es5 a.ts

public、protected、private

  • public,都可以访问

  • protected是提供给子类访问的,外部不可访问

  • private是私有的,只有自己内部可以访问

属性快速写法

下面两种写法是等同的:

class Person {
    private _name:string;
    private _age: number;
    
    constructor(name: string, age: number) {
        this._name = name;
        this._age = age;
    }
}
class Person {

    constructor(private name: string, private age: number) {
    }
    
}

继承

class Animal {
    protected _name: string;

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

    public sayHello(): void {
        console.log("动物叫~")
    }
}

class Dog extends Animal {
}

class Cat extends Animal 
}

// 子类继承了父类的所有非私有方法和属性,包括构造器
let d: Dog = new Dog("旺财");
let c: Cat = new Cat("猫大姐");

多继承:不支持

不支持多继承。

子类新增方法

给狗增加跑的方法:

class Dog extends Animal {
    public run():void {
        console.log(`${this._name}在跑~`)
    }
}
d.run(); // dog类对象才能调用run

方法重写

class Dog extends Animal {
    public run():void {
        console.log(`${this._name}在跑~`)
    }
    
    override sayHello() {
        console.log("汪汪");
    }
}

class Cat extends Animal {
    override sayHello() {
        console.log("喵喵");
    }
}

super关键字

class Cat extends Animal {
    override sayHello() {
        super.sayHello(); // 先调用父类的sayHello方法
        console.log("喵喵");
    }
}

构造器重写

class Cat extends Animal {
    constructor() {
        super("猫大姐"); // 必须调用父类的构造
    }

    override sayHello() {
        super.sayHello(); // 必须先调用父类的sayHello方法,不写不可
        console.log("喵喵");
    }
}
let c: Cat = new Cat();

抽象类

抽象类不可以用于创建实例。抽象类中可以定义抽象方法,抽象方法没有方法体,且必须必须被重写:

abstract class Animal { 
    protected _name: string;

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

    public abstract sayHello(): void;
}

class Dog extends Animal {
    public run(): void {
        console.log(`${this._name}在跑~`)
    }

    sayHello() { // 因为是抽象方法,override可以省略
        console.log("汪汪");
    }
}

class Cat extends Animal {
    constructor() {
        super("猫大姐"); // 必须调用父类的构造
    }

    override sayHello() { 
        super.sayHello(); // 先调用父类的sayHello方法
        console.log("喵喵");
    }
}

接口

// 接口不仅可以定义方法,还可以定义属性
interface A {
    name: string;
    age: number;

    sayHello(): void;
}

interface B {}

// 实现接口
// 接口可以多实现
class B implements A, B {
    age: number;
    name: string;

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

    sayHello(): void {
        console.log(`hello ${this.name}`)
    }

}

函数式接口

interface Action {
    (event: string): void
}
transition: function (event: string, action: Action) {
	action()
}

最后更新于