I'm often in a situation where I have a class that contains a collection. I'd like external code to be able to iterate over this collection, but not modify it.
I end up writing something like this:
def iter
@internal_collection.each do |o|
yield o
end
end
This allows the external code to do:
object.iter do |o|
do_something(o)
end
There must be a more elegant way of writing the "iter" method. Any ideas?
Before elegance, I would make sure I return an Enumerator
if no block is given.
This way your users can do object.iter.with_index do |obj, i|
An easy way to do this is and shorten your code is:
def iter(&block)
@internal_collection.each(&block)
end
In other circumstances, you might want to simply return a copy...
def collection
@internal_collection.dup
end
As far as explicitly writing the method goes, that's about as simple as it gets. But I think what you're after is the Forwardable module. Your code would look like this:
require 'forwardable'
class YourClass
extend Forwardable
def_delegator :@internal_collection, :each, :iter
end
Or if you wanted, you could delegate the whole Enumerable protocol to your internal collection and get all the standard Enumerable behavior that your internal collection features:
class YourClass
extend Forwardable
def_delegators :@internal_collection, *Enumerable.instance_methods
end
I'd use dup
and freeze
on your internal collection, then expose it to the world:
def collection
@internal_collection.dup.freeze
end
collection.map!(&:to_s) #=> raise RuntimeError: can't modify frozen Array
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.