我經常處於一種包含集合的類中。我希望外部代碼能夠遍歷這個集合,但不能修改它。在Ruby中返回一個迭代器或不透明集合
我寫出來是這樣的:
def iter
@internal_collection.each do |o|
yield o
end
end
這使得外部代碼來執行:
object.iter do |o|
do_something(o)
end
必須有書面的「ITER」方法的更優雅的方式。有任何想法嗎?
我經常處於一種包含集合的類中。我希望外部代碼能夠遍歷這個集合,但不能修改它。在Ruby中返回一個迭代器或不透明集合
我寫出來是這樣的:
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
或者,如果你願意,你可以委託整個可枚舉協議內部收集和獲得所有的標準可枚舉的行爲,你的內部集合特點:
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
似乎必須創建集合的重量級副本 - 因此如果頻繁調用方法效率低下。 –
我忘記說了,我想: def iter return @ collection.each end 但我相信沒有用。 –