たのしいRuby 第21章 Mix-in

21章に入る前に、昨日の復習をしておきたいと思う。やはりyieldの理解度が足りない。

yieldの復習。

昨日、イマイチわからなかったのが、何処のブロック呼び出しなのか。

プログラミングRuby言語編の4章に答えはあった。

シンプルにyieldを呼び出してみる。

def hello
  yield
  yield
  yield
end
hello {puts "Hello, yield World!!"}
#=> Hello, yield World!!
#=> Hello, yield World!!
#=> Hello, yield World!!

helloで指定したブロックを呼び出してます。シンプルだとわかりやすいっすね。

「yield 引数」だった場合は、

def hello_itelator
  (1..3).each do |i|
    yield "#{i}times"
  end
end
hello_itelator {|message| puts "Hello, #{message} yield World!!"}
#=> Hello, 1times yield World!!
#=> Hello, 2times yield World!!
#=> Hello, 3times yield World!!
message の中に「3times」という文字が入りました。yieldを呼ぶと、
def hello_itelator
  (1..3).each do |i|
    puts "Hello, #{i}times yield World!!"
  end
end

こんな感じに展開されるようです。

yieldは呼び出し元のブロックを実行する機能を備えている事がわかりました。C言語の関数ポインタみたいですね。

ところで、yieldって何て読むの?

おぉ。JavaScriptにもyield

IT戦記 - JavaScript 1.7 の yield が凄すぎる件について
yield波はJavaScriptにも波及しているようです。

と、思ったけど、

avaScriptのyieldは値をreturnする。次回の呼び出しはyieldしたところからスタートする。関数を一時停止させる役目があるだけだった・・・。

"ブロックを呼び出す機能は無い。"

Rubyとは全然、全く関係ない!!!!!!!!!!!!!激しくツマンネ。ガックリ来た・・・orz

Mix-inって何だぁ?

継承関係を保ったまま"機能だけ"継承する仕組みらしい。

class Array < Object
  include Enumerable
end

ArrayはObjectを継承し、機能としてEnumerable(eachとかsortとか)を提供する。

Javaだと、いちいち委譲しなければいけないところを、モジュールとして提供することによって、継承関係を崩さずに、新しい機能を追加出来る!!

つまり・・・プログラマは、機能を作ることに集中することが出来る!!

楽しみですねぇ〜。では、遅めの21章スタート。

モジュールを作ってみる。

HumanクラスとRabbitクラスを作って、動けぇ〜と命令してみます。

module Walk
  def move
    puts "歩きます。"
  end
end

module Jump
  def move
    puts "ジャンプします。"
  end
end

class Animal
  attr_accessor :name
end

class Human < Animal
  include Walk
end

class Rabbit < Animal
  include Jump
end

tanaka = Human.new
puts tanaka.name = "たなか"
tanaka.move
#=> たなか
#=> 歩きます。

pickaxe = Rabbit.new
puts pickaxe.name  = "ピッケル"
pickaxe.move
#=> ピッケル
#=> ジャンプします。

moduleをincludeすることで、共通する機能をまとめることが出来ました。カンタンですね。

組込みモジュールをinclude

昨日作ったBookクラスを利用して、ComparableやEnumerableをインクルードしてみた。

長いのでソースは略。

  • Comparableは<=>を定義する必要がある。
  • Enumerableはeachを定義する必要がある。

色々ルールがありそうです。