在Ruby中返回迭代器或不透明集合

时间:2012-11-27 03:56:58

标签: ruby collections iterator

我经常遇到一个包含集合的类。我希望外部代码能够迭代这个集合,但不能修改它。

我最终写了这样的东西:

def iter
  @internal_collection.each do |o|
     yield o
  end
end

这允许外部代码执行:

object.iter do |o|
    do_something(o)
end

必须有一种更优雅的方式来编写“iter”方法。有什么想法吗?

3 个答案:

答案 0 :(得分:2)

在优雅之前,如果没有给出阻止,我会确保返回Enumerator

这样您的用户就可以object.iter.with_index do |obj, i|

一种简单的方法是缩短您的代码:

def iter(&block)
  @internal_collection.each(&block)
end

在其他情况下,您可能只想返回一份副本......

def collection
  @internal_collection.dup
end

答案 1 :(得分:1)

就明确编写方法而言,这就像它获得的一样简单。但我认为你所追求的是Forwardable模块。你的代码看起来像这样:

require 'forwardable'

class YourClass
  extend Forwardable
  def_delegator :@internal_collection, :each, :iter
end

或者,如果您愿意,可以将整个Enumerable协议委托给内部集合,并获得内部集合所具有的所有标准Enumerable行为:

class YourClass
  extend Forwardable
  def_delegators :@internal_collection, *Enumerable.instance_methods
end

答案 2 :(得分:0)

我在您的内部收藏中使用dupfreeze,然后将其展示给全世界:

def collection
  @internal_collection.dup.freeze
end

collection.map!(&:to_s) #=> raise RuntimeError: can't modify frozen Array