Iterator その2

Rubyっぽく、まず思いついたのはこんな感じです。

module Iterator2
  class Book
    def initialize(name)
      @name = name
    end
    attr_reader :name
  end
  class BookShelf
    def initialize
      @books = []
    end
    def append(book)
      @books << book
    end
    def each(&block)
      @books.each &block
    end
  end
end

include Iterator2
book_shelf = BookShelf.new
book_shelf.append(Book.new("Hello, Ruby vol.1"))
book_shelf.append(Book.new("Hello, Ruby vol.2"))
book_shelf.append(Book.new("Hello, Ruby vol.3"))
book_shelf.each { |book| puts book.name }

=>
Hello, Ruby vol.1
Hello, Ruby vol.2
Hello, Ruby vol.3

内部イテレータになっています。ブロックいいですね、ブロック。
Ruby的にあまりに普通すぎて、すでにパターンなのか疑問です。

また、eachメソッドを定義してある場合Enumerableモジュールを
includeすることで、様々なメソッドが使えるようになります。

module Iterator2
  class Book
    def initialize(name)
      @name = name
    end
    attr_reader :name
  end
  class BookShelf
    include Enumerable
    def initialize
      @books = []
    end
    def append(book)
      @books << book
    end
    def each(&block)
      @books.each &block
    end
  end
end

include Iterator2
book_shelf = BookShelf.new
book_shelf.append(Book.new("Hello, Ruby vol.1"))
book_shelf.append(Book.new("Hello, Ruby vol.2"))
book_shelf.append(Book.new("Hello, Ruby vol.3"))
p book_shelf.map { |book| book.name.slice(/(vol.+)/, 1) }

=>
["vol.1", "vol.2", "vol.3"]

楽しいですね。もっと素敵なコードになるかな?