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 对象的构造函数。

相关推荐
passerby606115 分钟前
完成前端时间处理的另一块版图
前端·github·web components
掘了22 分钟前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅25 分钟前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅1 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅1 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment1 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
Cobyte2 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc