13面向对象之class下

一. 成员可见性

  • 有以下几种
    • public 类外可见
    • private 类内可见
ts 复制代码
class Person {
  private friend?: Person; //
  constructor(public name: string, friend?: Person) {
    this.friend = friend;
  }
  xxx() {
    this.friend; // 内部是可以用
  }
}

const p = new Person('Alice');
p.friend; //默认是public可见,如果前面加了private则没有这个属性,会报错
  • protected 子类可见
ts 复制代码
class Person {
  protected friend?: Person; //
  constructor(public name: string, friend?: Person) {
    this.friend = friend;
  }
}

const p = new Person('Alice');

class User extends Person {
  declare friend: User; // 重写一个属性的类型
  constructor(public id: number, name: string, friend?: User) {
    super(name, friend);
  }
  xxx() {
    this.friend; // 子类可以用,可以认为只有这个家族可以用
  }
}
  • 真私有属性,以上的private编译成js之后没有类型,依然可以调用,前面+#就是真正的私有属性,编译成js之后不会被擦除,因为这其实是js的语法
ts 复制代码
class Person {
  #friend?: Person; //
  constructor(public name: string, friend?: Person) {
    this.#friend = friend;
  }
}

二. static属性与static block

ts 复制代码
class Person {
  static xxx = 1;
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

Person.xxx; // 这就是Person上的属性,其实就是Person.xxx = 1,这个叫做类属性或者静态属性 
  • 需要注意static name会报错,同样也不能声明 prototype, length 等函数本身有的属性
ts 复制代码
class Person {
  static name = 1; // 会报错,因为js的类是靠函数模拟的,函数本身就有name的属性
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}
  • static可以用来表达类的共有属性,通过类属性来表达原型上共有属性的概念
ts 复制代码
class Person {
  static 种族 = '人类'; // 这个种族是所有对象共有的属性
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}
  • static block,假如有需求,需要在类里面获取某个计数
js 复制代码
class Foo {
  static #count = 0;
  static {
    // 意思是这段代码在类创建的时候使用,初始化私有属性
    const count = loadFromLocalStorage() || 0;
    Foo.#count += count;
  }
  constructor() {
    console.log(Foo.#count);
  }
}

三. 类加泛型

  • 例子一
ts 复制代码
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);
  }
}

const h = new Hash<string | number, string | number>();

h.set('name', 'hi');
h.get('name');

h.set([1, 2], 'hi'); // 会报错
  • 例子二,继承
ts 复制代码
class Hash<K, V> extends Map<K, V> {
  destroy() {
    this.clear();
  }
}

四. class表达式,其实就是匿名class

ts 复制代码
const Rectangle = class {
  constructor(public height: number, public width: number) {}
  area() {
    return this.height * this.width;
  }
};
const r = new Rectangle(100, 200);

五. 抽象类(不常用)

  • 为什么要有抽象类
    • interface只写类型,class又写类型又写实现,而抽象类就是为了实现一部分
ts 复制代码
abstract class C {
  // 也可以全部不实现,当成interface
  abstract name: string;
  age: number;
  constructor(age: number) {
    this.age = age;
  }
  abstract a(): number;
  abstract b(): number;
}

class D extends C {
  name: string;
  constructor(name: string) {
    super(18);
    this.name = name;
  }
  a() {
    return 1;
  }
  b() {
    return 2;
  }
}

const c = new D('Frank')

六. 把类当作参数

ts 复制代码
class Person {
  constructor(public name: string) {}
}

// 方式一
function f(X: typeof Person) {
  const p = new X('frank');
  console.log(p.name);
}

f(Person);

function ff(x: string) {
  console.log(x);
}
ff('hello'); // 我们可以发现,函数上的类型要比传入的类型范围大

// 方式二
function f2(X: new (name: string) => Person) {
  const p = new X('frank');
  console.log(p.name);
}

// f2(Person)的本质 (name: string) => obj

function ff2(x: (name: string) => string) {
  // ff2 类比f2
  x('frank');
}
ff2((name) => 'hello'); // 下面的返回值实际上比上面的高一点

第二种方式比较难理解,function f2(X: new (name: string) => Person)这是函数 f2 的定义。它接受一个参数 X,其中 X 的类型是一个构造函数,该构造函数接受一个名为 name 的字符串参数,并且该构造函数的返回类型必须是 Person

const p = new X('frank')在函数内部,它使用构造函数 X 创建了一个新的对象 p,并传递了 frank 作为参数。这段代码的关键点在于它使用了 TypeScript 中的函数类型签名来限定参数 X 的类型,确保 X 是一个能够创建 Person 对象的构造函数。

相关推荐
百万蹄蹄向前冲1 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5812 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路2 小时前
GeoTools 读取影像元数据
前端
ssshooter3 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry3 小时前
Jetpack Compose 中的状态
前端
dae bal4 小时前
关于RSA和AES加密
前端·vue.js
柳杉4 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化
lynn8570_blog4 小时前
低端设备加载webp ANR
前端·算法
LKAI.5 小时前
传统方式部署(RuoYi-Cloud)微服务
java·linux·前端·后端·微服务·node.js·ruoyi
刺客-Andy5 小时前
React 第七十节 Router中matchRoutes的使用详解及注意事项
前端·javascript·react.js