Tuesday, March 06, 2007

module_function [Ruby]

ziddik ถามเรื่องพฤติกรรมแปลกๆของ module_function
สำหรับคนที่ไม่รู้จัก module_function ลองมาดูว่ามันคืออะไรก่อน

สมมติเรา define Library math ไว้แบบนี้
module Math
def sin(x)
...
end
end


ปัญหาก็คือ คนใช้ต้อง include Math ก่อน
จึงจะใช้ได้
include Math
puts sin(10)

ซึ่งดูไม่สะดวกนัก
เช่นอาจจะเกิด name conflict ได้ง่าย

module function เข้ามาช่วยในจุดนี้โดย
module Math
def sin(x)
...
end

module_function :sin
end

จะทำให้เราสามารถเรียกใช้แบบนี้ได้
Math.sin(10)
หรือ
include Math
sin(10)


ขั้นตอนภายในจะแปลกๆหน่อยตรง
1. มันจะ copy function sin เป็น instance method อันใหม่
มี code แยกออกไปจากกัน (ไม่ share กัน)
2. มันจะ mark method ให้กลายเป็น private

ส่วนคำถามว่าทำไม มันถึง mark ให้เป็น private
มีคนพยายามเดาใจ Matz เหมือนกัน
แต่ผมอ่านแล้วก็ยังไม่เข้าใจ
Re: module_functions are private?

ส่วนตัวอย่างในคำถามของ ziddik
ถ้าอยากให้ใช้ได้ ต้องเขียนเป็นแบบนี้
module HelloModule
Version = "1.0"

def hello(name)
puts("Hello, #{name}. ")
end

module_function :hello
end


class Hello
include HelloModule
def myHello(name)
hello(name)
end
end

หรือจะ ใส่ public :hello ใน class Hello ก็ได้
แต่ตามที่ใน mailing list บอก
การทำเช่นนี้อาจจะเปิดโอกาสให้
shooting yourself in the foot.

Note: ผม search code ใน rails ดู
พบว่ามีการใช้ module_function อยู่นิดหน่อย
ใน package actionMailer กับ actionWebService
(ใช้อยู่นิดเดียว)

Related link from Roti

1 comment:

ziddik::zdk said...

ขอบคุณมากๆครับ p'pok
ถ้าให้เดาคงเอาไว้ป้องกันความยุ่งเหยิงของโค้ดมั้ง