define_method
動的にメソッドを追加する。
ポイントは1つのメソッドで複数のメソッドを定義できる所にある。
# 1から1000までのxの倍数を返す。
def multiple_method(x)
(1..1000).each_with_object([]) do |number, array|
if number % x == 0
array << number
end
end
end
(2..5).each do |x|
define_method("multiple_of_#{x}") do
multiple_method(x)
end
end
print multiple_of_2
print multiple_of_3
print multiple_of_4
print multiple_of_5
## 下記改良版
def multiple_method(multiple, range=1000)
block_method = proc { |argument|
(1..range).each_with_object([]) do |number, array|
if number % argument == 0
array << number
end
end
}
(1..multiple).each do |x|
define_method("multiple_of_#{x}") do
block_method.call(x)
end
end
end
send
レシーバの持っているメソッドを引数にして呼び出す。
["upcase", "downcase", "capitalize"].each do |method_name|
puts "toKYo".send("#{method_name}")
end
class_eval
classの外からでもメソッドを定義できる。
class MyClass
def sum_value_1
puts "a" * 100
end
end
MyClass.class_eval do
def sum_value_2
puts "i" * 100
end
end
instance_eval
ブロック内で変数を利用する
class MyClass
attr_accessor :tokyo, :osaka
def initialize(tokyo="tokyo", osaka="osaka")
@tokyo = tokyo
@osaka = osaka
end
end
aaa = MyClass.new
aaa.tokyo
aaa.instance_eval do
puts "#{@tokyo} と #{@osaka}は大都市です。"
end
Procオブジェクト
ブロックをオブジェクトに格納する。
array = ["asakusa", "ginza", "shibuya", "ikebukuro", "sinjyuku", "ueno"]
aaa = proc { |b|
b.detect{ |a| a =~ /^asa/}
}
bbb = Proc.new{ |b|
b.detect{ |a| a =~ /^gin/}
}
ccc = lambda{ |b|
b.detect{ |a| a =~ /^ue/}
}
puts aaa.call(array)
puts bbb.call(array)
puts ccc.call(array)