TS-抽象类和静态成员

1,抽象类

1,为什么需要抽象类

有时,某个类只表示一个抽象的概念,主要用于提取子类的公共成员,而不是直接创建它的实例对象。此时,这个类可以作为抽象类。

实现:在类名前加 abstract,抽象类不可以通过 new 来创建实例对象。

2,抽象成员

有时,一些公共成员是必须存在的,但还不确定成员的值或具体实现。因为,需要一种强约束,让继承的子类必须实现这些成员。

也就是说,抽象类中定义的抽象成员,在子类中必须实现。

如果子类也是抽象类,则可以不实现父类中的抽象成员或方法。

子类的3种实现方式:

abstract class Chess {
    abstract readonly name: string;
}

// 第1种
class Horse extends Chess {
    readonly name: string = "马";
}

// 第2种
class Pao extends Chess {
    readonly name: string;
    constructor() {
        super();
        this.name = "炮";
    }
}

// 第3种
class Soldier extends Chess {
    get name() {
        return "兵";
    }
}

3,设计模式-模板模式

当某个公共方法中,一部分是公共逻辑,一部分又是私有逻辑(需要再子类中实现)。

此时,可以不将该方法定义为抽象方法,而是将那部分私有逻辑定义为抽象方法,并在当前方法中调用即可。

这样的强约束,可以只关注子类需要实现的东西,其他的父类已经完成。

abstract class Chess {
    abstract readonly name: string;
    move(targetX: number, targetY: number): boolean {
        // 第1和第2步属于公共逻辑
        // 1,边界条件判断
        // 2,目标位置是否有己方棋子

        // 第3步属于私有逻辑:不同兵种的移动规则(需要在子类中实现)
        if (this.rule(targetX, targetY)) {
            console.log("移动成功");
            return true;
        } else {
            return false;
        }
    }

    protected abstract rule(targetX: number, targetY: number): boolean;
}

class Horse extends Chess {
    protected rule(targetX: number, targetY: number): boolean {
        return true; // 简单实现,做测试使用。
    }
    readonly name: string = "马";
}

const horse = new Horse();
horse.move(2, 3);

2,静态成员

1,什么是静态成员

指附着在类上的成员(相当于构造函数的属性),通过static修饰。

每个实例成员的相同属性,理论上是不一样的,所以那些相同的属性应该作为静态成员,附着在类上。

构造函数或非静态方法中的this指向实例对象,如果要访问当前类,直接使用类名即可。

静态方法中的this指向当前类。

class User {
    static users: User[] = [];
    constructor(public id: string, public pwd: string, public name: string, public age: number) {
        User.users.push(this);
    }

    static login(loginId: string, loginPwd: string): User | undefined {
        // 静态方法中 this 指向当前类
        return this.users.find((user) => user.id === loginId && user.pwd === loginPwd);
    }

    sayHello() {
        console.log(`我是${this.name}`);
    }
}

new User("u1", "pwd1", "用户1", 18);
new User("u2", "pwd2", "用户2", 188);

console.log(User.users);

const user = User.login("u1", "pwd1");
if (user) {
    user.sayHello();
}

2,设计模式-单例模式

某些类的实例对象,在系统中只允许存在一个,为了避免开发者随意创建实例对象而产生预期之外的错误,可以使用单例模式进行强约束。

构造函数私有化或抽象类,都不允许 new 实例对象。

class User {
    private constructor() {}

    private static _user?: User;

    static createUser() {
        if (!this._user) {
            this._user = new User();
        }
        return this._user;
    }
}

const u1 = User.createUser();
const u2 = User.createUser();
console.log(u1 === u2);

下面的方式也可以创建单例,但有一些缺陷。

  • 实例对象一开始就创建了,不是在需要时才创建。
  • 做不到在创建单例对象时,提前执行一些代码。
class User {
    private constructor() {}

    static readonly singleUser = new User()
}

const u1 = User.singleUser;
const u2 = User.singleUser;
console.log(u1 === u2);

以上。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下雪天的夏风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值