面向对象之 class(下)
四种成员可见性
public(类外可见)
public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public
private(类内可见)
private 修饰的属性或方法是私有的,不能在声明它的类的外部访问
protected(子类可见)
protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的
#var(真私有属性)
上面的都是 TS 的语法(访问修饰符),而 #var 是 JS 的语法,在属性名前面加上 # 即可做到真正的属性私有
注意:由于 private 是 TS 的语法,在类型被擦除后就没了;真正的私有属性得使用 # 才能做到
static 属性与 static block
我们可以使用 static 来定义一个静态属性,静态属性只能通过类名来访问
1 2 3 4 5 6 7 8 9 10 11
| class Dog { static kind = "狗";
constructor() { } }
const dog = new Dog(); console.log(dog.kind); console.log(Dog.kind);
|
注意:用 static 声明的属性,其名称不能是 name、prototype、length、arguments、caller 其中之一
因为 js 中的类都是通过函数来模拟的
static block 主要用来初始化私有属性(类外部无法初始化私有属性)
1 2 3 4 5 6 7 8 9 10
| class Foo { static #count = 0; static { const count = loadFromLocalStorage() || 0; Foo.#count += count; } constructor() { console.log(Foo.#count); } }
|
类与泛型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Hash<K, V> { map: Map<K, V> = new Map(); set(key: K, value: V) { this.map.set(key, value); } get(key: K) { return this.map.get(key); } }
class Hash<K, V> extends Map<K, V> { destroy() { this.clear(); } }
|
class 表达式
将匿名的 class 赋值给一个变量
1 2 3 4 5 6 7
| const Rectangle = class { constructor(public height: number, public width: number) {} area() { return this.height * this.width; } }; const r = new Rectangle(100, 200);
|
抽象类
abstract 用于定义抽象类和其中的抽象方法
1 2 3 4 5 6 7 8
| abstract class Base { abstract getName(): string; printName() { console.log('Hello, ' + this.getName()); } } const b = new Base();
|
抽象类:
- 不能被直接实例化:
new Base() ❌ 会报错
- 必须通过子类继承实现
- 可以包含具体实现(如
printName() 方法)
- 可以定义抽象方法
抽象方法:
- 只有声明,没有实现(没有方法体,比如
getName())
- 强制子类必须实现这些方法
- 定义核心接口,确保子类行为一致性
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| abstract class Base { abstract getName(): string; printName() { console.log('Hello, ' + this.getName()); } } class Derived extends Base { getName() { return 'world'; } } const d = new Derived(); d.printName();
|
可以看出,抽象类是介于 interface 和 class 之间的一种写法
如果一个 class 中的属性全都是抽象属性,那么也可以直接把这个 class 当作 interface
把类当作参数(常用)
注意是把类作为参数,而不是把类的实例化对象作为参数
1 2 3 4 5 6 7 8 9 10 11 12
| class Person { constructor(public name: string) {} sayHi() { console.log(`Hi, I am ${this.name}`); } } function greet(constructor: typeof Person) { const p = new constructor('ClariS'); p.sayHi(); } greet(Person); greet(new Person('ClariS'));
|
1 2 3 4 5 6 7 8 9 10 11 12
| class Person { constructor(public name: string) {} sayHi() { console.log(`Hi, I am ${this.name}`); } } function greet(constructor: new (name: string) => Person) { const p = new constructor('ClariS'); p.sayHi(); } greet(Person); greet(new Person('ClariS'));
|