【问题标题】:Adding methods to es6 child class向 es6 子类添加方法
【发布时间】:2017-09-07 15:22:17
【问题描述】:

我想创建一个从 Array 派生的新类,除了常规的数组方法外,它还有自己的方法。

export class ObjectCollection<T extends Iidentifier> extends Array<T> {

  constructor(collection: T[] = []) {
    super(...collection);
  }

  // used for getting instance from a collection of objects
  public getInstance(id: Id) {
    return this.find(item => item.Id.toString() === id.toString()) || new 
    Array<T>();
  }

}

我也有继承自该类的子类。

export class TargetCategories extends ObjectCollection<TargetCategory> {

  constructor(categories: TargetCategory[] = []) {
    super(categories);
  }

  public getCategoryType(id: Iidentifier): string {
    return this[id].Category.length < 2 ? "dummy" : "saved";
  }

}

当我实例化一个 TargetCategories 对象时,我只能使用数组中的方法。我无法调用 getCategoryType 和 getInstance 之类的东西。

【问题讨论】:

  • 在运行时还是在编译时?你遇到了什么错误 ?您如何创建和使用 TargetCategories 的实例?
  • 我用全新的 TargetCategories() 进行了尝试,但仍然无法从实例中访问这些方法。我可以访问方法的唯一方法是,如果我像使用类方法一样使用它,例如 TargetCategories.prototype.say
  • 是编译时错误还是运行时错误?你能分享你的代码吗?我使用了你的代码,填写了缺失的部分,它可以在 chrome 中运行、编译和运行。
  • 运行时错误。常量目标 = 新 ObjectCollection(); console.log(target.indexOf(new TargetCategory())); console.log(ObjectCollection.prototype.say()); console.log(target.say());它将在最后一个失败。
  • 你要转换成什么?

标签: javascript typescript ecmascript-6 prototypal-inheritance


【解决方案1】:

我已经把它们放在一起,修复了一些小错误,看起来还可以。

type Id = number;
interface Iidentifier {
    Id: number;
}

class ObjectCollection<T extends Iidentifier> extends Array<T> {

  constructor(collection: T[] = []) {
    super(...collection);
  }

  // used for getting instance from a collection of objects
  public getInstance(id: Id) {
    return this.find(item => item.Id.toString() === id.toString()) || new 
    Array<T>();
  }

}

interface TargetCategory extends Iidentifier {
    Category: number[];
}

class TargetCategories extends ObjectCollection<TargetCategory> {

  constructor(categories: TargetCategory[] = []) {
    super(categories);
  }

  public getCategoryType(id: Iidentifier): string {
    return this[id.Id].Category.length < 2 ? "dummy" : "saved";
  }
}

let tc = new TargetCategories();
tc.getInstance(1);
tc.getCategoryType({ Id: 2 });

【讨论】:

  • 不要扩展Array 您的代码将根据转译方式以及在哪个 JavaScript 运行时执行而严重崩溃。这是标准机构未能创建良好的 ES2015 迁移路径。目前没有可靠的方法来做到这一点。
  • @AluanHaddad 这是否意味着它可能会起作用?以及如何完全包裹数组?它会做一些工作,但它不可靠吗? class MyArray&lt;T&gt; implements Array&lt;T&gt; { private _array: Array&lt;T&gt;; }
  • 是的,它可能会起作用,也可能会失败……这是一种可悲的状况。包装在概念上是正确的方法,但 AFAIK 没有办法在不使用代理的情况下拦截数值的属性访问,这是另一个 ES2015 特性。整个事情一团糟。
  • @AluanHaddad 我不明白你。 get length(): number { return this._array.length; } 有什么问题?
  • 什么都没有。我只是说你不能在包装器上使用括号表示法。 a[i] 将不起作用。如果你不需要那个符号,那么包装一个数组绝对是要走的路。
【解决方案2】:

我找到了一种工作方式,但我怀疑这是唯一的方式,或者说是最干净的方式。

interface IDifferentArray {
    id: string | number;
}

export class DifferentArray<T extends IDifferentArray> extends Array<T> {

    public lengthMessage: () => void;
    public otherMethod: () => number;

    constructor(items: Array<T> = []) {
        super(...items);

        this.lengthMessage = function() {
            return `My length is ${this.length}`;
        }

        this.otherMethod = function() {
            return 12;
        }
    }
}

您可以访问本机数组方法、属性并添加您自己的实例方法。如果你把它放在构造函数之外,它将是一个类方法。

这就是它在常规 javascript 中的工作方式。我认为 es6/typescript 会模拟真正的 OOP,但我猜不是。

【讨论】:

  • 它与 OOP 无关,而与扩展特定的内置类型(例如 Array)有关,这些类型的某些行为会使转译到 ES5 出现问题。此外,如果您尝试使用 Java 编写代码,那么您就是在浪费时间。
猜你喜欢
  • 2017-12-27
  • 2021-07-19
  • 2020-08-03
  • 2017-07-03
  • 1970-01-01
  • 1970-01-01
  • 2011-05-23
  • 2012-01-22
相关资源
最近更新 更多