2

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

我最终写了这样的东西:

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

这允许外部代码执行以下操作:

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

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

4

3 回答 3

2

在优雅之前,我会确保我返回一个Enumeratorif 没有给出块。

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

一个简单的方法是缩短你的代码是:

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

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

def collection
  @internal_collection.dup
end
于 2012-11-27T05:56:31.343 回答
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
于 2012-11-27T06:22:35.160 回答
0

我会在您的内部收藏中使用dup和,然后将其公开:freeze

def collection
  @internal_collection.dup.freeze
end

collection.map!(&:to_s) #=> raise RuntimeError: can't modify frozen Array
于 2012-11-27T06:34:27.027 回答