Это пример уточнения вашего примера кода:
class MyClass
attr_accessor :items
def initialize(ary=[])
@items = ary
end
def each
@items.each do |item|
yield item
end
end
end
my_class = MyClass.new(%w[a b c d])
my_class.each do |y|
puts y
end
# >> a
# >> b
# >> c
# >> d
each
зацикливается на коллекции.В этом случае он зацикливается на каждом элементе в массиве @items
, инициализированном / созданном, когда я выполнял оператор new(%w[a b c d])
.
yield item
в методе MyClass.each
передает item
в прикрепленный блокдо my_class.each
.Получаемый item
назначается локальному y
.
Помогает ли это?
Теперь рассмотрим подробнее, как работает each
.Используя то же определение класса, вот некоторый код:
my_class = MyClass.new(%w[a b c d])
# This points to the `each` Enumerator/method of the @items array in your instance via
# the accessor you defined, not the method "each" you've defined.
my_class_iterator = my_class.items.each # => #<Enumerator: ["a", "b", "c", "d"]:each>
# get the next item on the array
my_class_iterator.next # => "a"
# get the next item on the array
my_class_iterator.next # => "b"
# get the next item on the array
my_class_iterator.next # => "c"
# get the next item on the array
my_class_iterator.next # => "d"
# get the next item on the array
my_class_iterator.next # =>
# ~> -:21:in `next': iteration reached an end (StopIteration)
# ~> from -:21:in `<main>'
Обратите внимание, что в последний next
итератор выпал из конца массива.Это потенциальная ошибка для НЕ при использовании блока, потому что, если вы не знаете, сколько элементов в массиве, вы можете запросить слишком много элементов и получить исключение.
Использование each
с блоком будет перебирать приемник @items
и останавливаться при достижении последнего элемента, избегая ошибки и сохраняя все в порядке и чистоте.