阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 多态与this类型

多态与this类型

作者:陈川 阅读数:55578人阅读 分类: TypeScript

多态与this类型

TypeScript中的多态性允许不同类型的对象通过统一的接口进行操作,而this类型则提供了对当前实例类型的动态引用。这两者结合能够实现更灵活的代码结构,特别是在继承和链式调用场景下。

多态的基本概念

多态性在TypeScript中主要通过接口和类继承实现。当不同类实现相同接口或继承相同基类时,它们可以被统一处理:

interface Animal {
  makeSound(): void;
}

class Dog implements Animal {
  makeSound() {
    console.log('Woof!');
  }
}

class Cat implements Animal {
  makeSound() {
    console.log('Meow!');
  }
}

function animalSound(animal: Animal) {
  animal.makeSound(); // 多态调用
}

const dog = new Dog();
const cat = new Cat();

animalSound(dog); // 输出: Woof!
animalSound(cat); // 输出: Meow!

this类型的动态特性

this类型表示"当前类的实例类型",它在运行时动态确定。这使得方法可以返回当前实例,便于实现链式调用:

class Calculator {
  value: number;

  constructor(value = 0) {
    this.value = value;
  }

  add(n: number): this {
    this.value += n;
    return this;
  }

  multiply(n: number): this {
    this.value *= n;
    return this;
  }
}

const calc = new Calculator();
calc.add(5).multiply(2); // 链式调用
console.log(calc.value); // 输出: 10

多态this与继承

当类被继承时,this类型会自动调整为子类类型,这在构建可扩展的类层次结构时非常有用:

class BaseClass {
  clone(): this {
    // 返回当前实例的副本
    return Object.create(this);
  }
}

class DerivedClass extends BaseClass {
  additionalMethod() {
    console.log('Additional method');
  }
}

const derived = new DerivedClass();
const cloned = derived.clone(); // 类型为DerivedClass,不是BaseClass
cloned.additionalMethod(); // 可以调用子类方法

接口中的this类型

接口也可以使用this类型来定义更灵活的契约:

interface Builder<T> {
  setOption<K extends keyof T>(key: K, value: T[K]): this;
  build(): T;
}

class PersonBuilder implements Builder<Person> {
  private options: Partial<Person> = {};

  setOption<K extends keyof Person>(key: K, value: Person[K]): this {
    this.options[key] = value;
    return this;
  }

  build(): Person {
    return new Person(this.options);
  }
}

const person = new PersonBuilder()
  .setOption('name', 'Alice')
  .setOption('age', 30)
  .build();

多态this的实际应用

在实际开发中,多态this常用于构建流畅API和扩展类功能:

class QueryBuilder {
  where(condition: string): this {
    // 添加where条件
    return this;
  }

  limit(count: number): this {
    // 设置limit
    return this;
  }
}

class MySQLQueryBuilder extends QueryBuilder {
  useIndex(index: string): this {
    // MySQL特定方法
    return this;
  }
}

const query = new MySQLQueryBuilder()
  .where('age > 18')
  .useIndex('age_index') // 子类方法
  .limit(10); // 父类方法

类型守卫与this

结合类型守卫可以创建更精确的类型判断:

class FileSystemObject {
  isFile(): this is File {
    return this instanceof File;
  }
  
  isDirectory(): this is Directory {
    return this instanceof Directory;
  }
}

class File extends FileSystemObject {
  read(): string {
    return 'file content';
  }
}

class Directory extends FileSystemObject {
  list(): string[] {
    return ['file1', 'file2'];
  }
}

function process(obj: FileSystemObject) {
  if (obj.isFile()) {
    obj.read(); // 这里obj被推断为File类型
  } else if (obj.isDirectory()) {
    obj.list(); // 这里obj被推断为Directory类型
  }
}

this参数的特殊用法

方法定义中的this参数可以约束方法的调用上下文:

function clickHandler(this: HTMLButtonElement) {
  this.disabled = true;
}

const btn = document.querySelector('button');
btn?.addEventListener('click', clickHandler); // 正确
// clickHandler(); // 错误:this上下文不符合

多态this的进阶模式

在复杂类型系统中,this类型可以与其他高级类型特性结合:

class Observable<T> {
  private subscribers: ((value: T) => void)[] = [];

  subscribe(callback: (value: T) => void): this {
    this.subscribers.push(callback);
    return this;
  }

  next(value: T): this {
    this.subscribers.forEach(cb => cb(value));
    return this;
  }
}

class NumberObservable extends Observable<number> {
  map(transform: (n: number) => number): this {
    // 实现map操作
    return this;
  }
}

const obs = new NumberObservable()
  .map(n => n * 2)
  .subscribe(console.log)
  .next(10); // 输出: 20

this类型与混入模式

this类型在混入(mixin)模式中特别有用,可以保持正确的类型推断:

type Constructor<T = {}> = new (...args: any[]) => T;

function Timestamped<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    timestamp = Date.now();
  };
}

function Activatable<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    isActive = false;

    activate(): this {
      this.isActive = true;
      return this;
    }
  };
}

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

const TimestampedActivatableUser = Activatable(Timestamped(User));
const user = new TimestampedActivatableUser('Alice');
user.activate();
console.log(user.timestamp, user.isActive);

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌