我经常遇到一个包含集合的类的情况。 我希望外部代码能够迭代此集合,但不能修改它。
我最终写了这样的东西:
def iter
@internal_collection.each do |o|
yield o
end
end
这允许外部代码执行以下操作:
object.iter do |o|
do_something(o)
end
必须有一种更优雅的编写"iter"方法的方式。 有什么想法吗?
在优雅之前,如果没有给出块,我会确保我返回一个Enumerator
。
这样,您的用户可以执行object.iter.with_index do |obj, i|
执行此操作的一种简单方法是缩短代码:
def iter(&block)
@internal_collection.each(&block)
end
在其他情况下,您可能只想返回副本...
def collection
@internal_collection.dup
end
就显式编写方法而言,这很简单。但我认为你所追求的是可转发模块。您的代码如下所示:
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
我会在您的内部集合上使用dup
和freeze
,然后将其公开给全世界:
def collection
@internal_collection.dup.freeze
end
collection.map!(&:to_s) #=> raise RuntimeError: can't modify frozen Array