2012-11-27 42 views
2

我經常處於一種包含集合的類中。我希望外部代碼能夠遍歷這個集合,但不能修改它。在Ruby中返回一個迭代器或不透明集合

我寫出來是這樣的:

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

這使得外部代碼來執行:

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

必須有書面的「ITER」方法的更優雅的方式。有任何想法嗎?

+0

我忘記說了,我想: def iter return @ collection.each end 但我相信沒有用。 –

回答

2

在優雅之前,如果沒有給出塊,我會確保返回Enumerator

這樣,你的用戶可以做object.iter.with_index do |obj, i|

一個簡單的方法來做到這一點,並縮短你的代碼是:

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

在其他情況下,你可能想簡單地返回副本...

def collection 
    @internal_collection.dup 
end 
1

只要明確地寫出方法就行了,就像它變得簡單一樣。但我認爲你所追求的是可轉換模塊。您的代碼應該是這樣的:

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 
+0

謝謝,這很好,只是爲了瞭解一般情況。 –

0

我會在你的內部集合使用dupfreeze,然後將其暴露在世人:

def collection 
    @internal_collection.dup.freeze 
end 

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

似乎必須創建集合的重量級副本 - 因此如果頻繁調用方法效率低下。 –