【问题标题】:Determine closest ancestor between list of classes确定类列表之间最近的祖先
【发布时间】:2021-06-23 09:13:55
【问题描述】:

考虑这个例子:

class Point {}
class Point2D extends Point {}
class Point3D extends Point2D {}
class FloatPoint extends Point {}

class Bar {}
class Foo extends Bar {}

const result = joinWithClosestAncestor([Point, Point2D, Point3D, FloatPoint, Bar, Foo])
// result === [[Point], [Point2D, Point], [Point3D, Point2D], [FloatPoint, Point], [Bar], [Foo, Bar]];

我正在尝试创建joinWithClosestAncestor,它接受一个类数组并返回一个对数组,其中第一个元素是类,第二个元素是输入类中最接近的祖先(如果有的话)。

在示例中,Point3D 是从 PointPoint2D 派生的,但因为 Point2D 在输入列表中并且与 Point3D 的相关性比 Point 更接近,所以改为选择它。我可以使用Class.prototype instanceof X 来确定它是否相关,但我无法比较关系的depth

有没有办法以某种方式比较不同类之间的depthinstanceof 以始终获得最接近的关系?还是其他方式?

【问题讨论】:

标签: javascript typescript class oop inheritance


【解决方案1】:

您可以在类构造函数上使用Object.getPrototypeOf() 来获取其直接超类构造函数。它找不到明显的 MDN 源代码,但 JavaScript for Impatient Programmers by Dr. Axel Rauschmayer 解释说发生这种情况是为了让 static 属性和方法被子类继承。

无论如何,由于您可以找到直接的超类构造函数,因此您可以沿着该链向上走,直到找到存在于您的数组中的东西,或者直到您离开链的末端。像这样的东西,例如:

function joinWithClosestAncestor(ctors: Array<new (...args: any) => any>) {
  const ret = [];
  for (let ctor of ctors) {
    const cur = [ctor];
    ret.push(cur);
    for (
      let parent = Object.getPrototypeOf(ctor);
      parent;
      parent = Object.getPrototypeOf(parent)
    ) {
      if (ctors.includes(parent)) {
        cur.push(parent);
        break;
      }
    }
  }
  return ret;
}

它会产生您正在寻找的结果,至少对于您给出的示例而言:

const result = joinWithClosestAncestor([Point, Point2D, Point3D, FloatPoint, Bar, Foo])
console.log(JSON.stringify(result.map(x => x.map(y => y.name))));
// [["Point"],["Point2D","Point"],["Point3D","Point2D"],
//  ["FloatPoint","Point"],["Bar"],["Foo","Bar"]]

Playground link to code

【讨论】:

    猜你喜欢
    • 2018-08-02
    • 2014-04-02
    • 2010-09-17
    • 1970-01-01
    • 2016-03-26
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多