Thursday, June 02, 2005

Ruby Message (method)

เอามาจาก "10 Things Every Java Programmer Should Know About Ruby"

ในการเรียกใช้ method
in ruby
obj.method

in java
obj.method()

ซึ่งดูแล้วน่าจะเหมือนกัน
แต่ลองดูตัวอย่างนี้

class VCR
def initialize
@messages = []
end

def method_missing(method, *args, &block)
@messages << [method, args, block]
end

def play_back_to(obj)
@messages.each do |method, args, block|
obj.send(method, *args, &block)
end
end
end


class VCR มี method หลักๆอยู่อันเดียวคือ
play_back_to ส่วน method_missing
จะใช้กรณีที่มีการเรียกใช้ method ที่ไม่ได้มีการ definition ไว้

อธิบายการทำงานได้ดังนี้
initalize เรียกใช้เมื่อมีการ new object
โดยจะทำการ initialize Array ที่ชื่อ message
(เครื่องหมาย @ หมายถึง instance variable)
จากนั้นถ้ามีการ call method ที่ไม่ได้ประกาศไว้
ให้ทำการเก็บ list ของ method, param, block ไว้ใน message Array
กรณีที่ call playback ก็ให้นำ method ทั้งหมดที่เก็บไว้ใน
message Array ออกมาเรียกใช้กับ object ที่ pass มา

ลองดูการนำไปใช้

require 'src/vcr'

vcr = VCR.new
vcr.sub!(/Java/) { "Ruby" }
vcr.upcase!
vcr[11,5] = "Universe"
vcr << "!"

string = "Hello Java World"
puts string

vcr.play_back_to(string)
puts string


ผลลัพท์ที่ได้

Hello Java World
HELLO RUBY Universe!


อธิบายเพิ่มเติมสำหรับคนที่ยังไม่คุ้น syntax ruby
โดยหลังจากที่เรา new VCR object แล้ว
ก็เรียกใช้ method sub!, upcase, array assignment([]=), concat(<<)
ซึ่งทั้งหมดนี้ไม่ได้มีการประกาศไว้ใน VCR Class เลย
ดังนั้น method ทั้งหมดก็จะถูกเก็บไว้ใน messages array
จากนั้นเมื่อมีการเรียกใช้ play_back_to
ก็จะนำเอา method เหล่านี้ออกมาเรียกใช้กับ
String ที่ pass เข้าไป

sub! -> inplace substitution
upcase! -> inplace upper case
[11,5]="Universe" -> เป็นการแทน char ที่ตำแหน่ง 11 โดยแทนที่ 5 ตัวอักษร
<<"!" -> concat ต่อท้าย

ดูแล้ว ก็รู้สึกว่า language มัน dynamic ดีจัง
เขียนแล้วคงจะสนุกดี (เพราะมี choice ให้ creative ได้หลายแบบ)
แต่น่าจะปวดหัวพอสมควร สำหรับการใล่ code
ที่เขียนด้วย ruby

Related link from Roti

No comments: