简体   繁体   中英

Typescript conditional inheritance

The goal is to create a prototype which can extends different classes. I need to create a class that extends either Mesh or Points of THREE.js. The subclass I made is the same for either of these cases. It cannot be interface.

class PointsElement extends THREE.Points {
  public name: string
  protected width: number
  protected height: number

  constructor (protected target: THREE.Scene | THREE.Group, protected properties: IElementProperties) {
    super()
    this.name = this.properties.name
    AutoBind(this)
  }

  public async preload () {
  }

  public async show () {
    this.target.add(this)
  }

  public async hide () {
    this.target.remove(this)
  }
}

class MeshElement extends THREE.Mesh {
  public name: string
  protected width: number
  protected height: number

  constructor (protected target: THREE.Scene | THREE.Group, protected properties: IElementProperties) {
    super()
    this.name = this.properties.name
    AutoBind(this)
  }

  public async preload () {
  }

  public async show () {
    this.target.add(this)
  }

  public async hide () {
    this.target.remove(this)
  }
}

What I want to do is to reduce the code by exclude the 'Element', as the body is the same in MeshElement and PointsElement, but each of these class extends different classes

It's a little quick and dirty but hopefully you get the idea as to what I mean by a factory pattern.

What you described is only 1 way of doing factory not the only.

enum Geometrics {
  Mesh = "Mesh",
  Points = "Points"
}

class Element {
  public isElement = true;
}

class Mesh extends Element {
  public type = Geometrics.Mesh;
}

class Point extends Element {
  public type = Geometrics.Points;
}

class GeometricsFactory<T extends Geometrics> {
  private shapesMap = new Map<Geometrics, typeof Mesh | typeof Point>([
    [Geometrics.Mesh, class Shape extends Mesh {}],
    [Geometrics.Points, class Shape extends Point {}]
  ]);

  constructor(private type: Geometrics) {}

  public getShape(): T extends Geometrics.Mesh ? typeof Mesh : typeof Point {
    const shape = this.shapesMap.get(this.type);
    if (shape) {
      return <T extends Geometrics.Mesh ? typeof Mesh : typeof Point>shape;
    }
    throw new Error(`Invalid shape type ${this.type}`);
  }
}

const MyMesh = new (new GeometricsFactory<Geometrics.Mesh>(Geometrics.Mesh).getShape())();
console.log(MyMesh.type);

const MyPoints = new (new GeometricsFactory<Geometrics.Points>(Geometrics.Points).getShape())();
console.log(MyPoints.type);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM