【问题标题】:Implement Iterable interface with default array iterator使用默认数组迭代器实现 Iterable 接口
【发布时间】:2021-09-14 18:43:17
【问题描述】:

我有一个实现 Tuple 的 Vector 类,像这样(简化代码,Tuple 接口基本上只是一个没有方法和固定大小 N 的数组):

interface Tuple<T, N extends number> extends ArrayLike<T>, Iterable<T> {
    0: T
    length: N
}

export class Vector<N extends number> implements Tuple<number, N> {
    //Implementation
}

现在我想让我的 Vector 可迭代。当我创建一个 Tuple 类型的变量时,它已经是可迭代的,但 Vector 显然不是:

let t: Tuple<number,2> = [1,2]
for (const iterator of t) {...} //works

let v = new Vector([1,2])
for (const iterator of v) {....} //Type 'Vector<2>' must have a '[Symbol.iterator]()' method that returns an iterator.

我的问题是:如何在向量中实现“默认”迭代器,这样我就不必再次编写函数了?我可以以某种方式复制元组或数组迭代器吗? 如果这是不可能的,那么定义我的迭代器的最佳方法是什么?现在,我已将这个(生成器)方法添加到我的 Vector 类中:

*[Symbol.iterator](): Iterator<number, any, undefined> {
       for (let i = 0; i < this.length; i++) {
           yield this[i]
       }
 }

它有效,但我不能 100% 确定它实际在做什么,返回值 Iterator 指定了什么,以及是否有更好的方法来做到这一点。

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    如果你希望你的类是可迭代的,你肯定必须以某种方式提供一个迭代器。但是,如果您只是想将迭代转发到您的类的属性,那么我认为您只需要实现一个 getter,它可以从您想要迭代的任何地方获取迭代器。

    例如:

    export class Vector<N extends number> implements Tuple<number, N> {
      constructor(public values: Tuple<number, N>) {}
    
      get [Symbol.iterator]() {
        return this.values[Symbol.iterator]
      }
    }
    

    现在当你迭代它时,你实际上是从内部属性values 中获取迭代器来迭代。

    Playground


    有没有办法不将“值”保留为对象属性(例如,通过直接在构造函数中分配 Symbol.iterator)?

    当然。默认情况下,迭代器属性是只读的,但是如果您在类中声明迭代器类型,那么您就是说它是可写的。然后在构造函数中赋值给迭代器属性。

    class Vector {
      [Symbol.iterator]: () => Iterator<number>
      
      constructor(public values: number[]) {
        this[Symbol.iterator] = this.values[Symbol.iterator]
      }
    }
    

    See playground

    【讨论】:

    • 谢谢,效果很好!有没有办法不将“值”保留为对象属性(例如,通过直接在构造函数中分配 Symbol.iterator)?
    • @Devoev 当然,为什么不呢?我已经更新了我的答案。
    • 有没有办法指定迭代器的类型,以便接收者知道迭代器产生一个元组?
    • @JonasRøssum 这是一个很好的问题,值得成为一个新的问题帖子:)
    • 是的,我想很难将它放入 cmets 中。我将创建一个新问题并将其链接到此处。编辑:在这里发布单独的问题:stackoverflow.com/questions/69184150/…
    猜你喜欢
    • 2011-08-28
    • 2011-11-14
    • 2014-10-01
    • 2010-10-10
    • 2011-02-25
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    • 2017-10-26
    相关资源
    最近更新 更多