此篇文章對剛學 Ruby 程式語言的朋友們來說,應該算是比較進階的題目。其實我已看過了網路上相關文章後,也是似懂非懂的,ㄧ直到閱讀"Metaprogramming Ruby" 後,才有了較深刻的了解。但文章內如有錯誤或是有不完整的地方都歡迎各位大大不吝指教!
"A method like this one, which is specific to a single object, is called Singleton Method" from Meatprogramming Ruby
Singleton method 是讓物件自己擁有專屬的方法,任何其它物件或是類別都無法使用。但在開始介紹 singleton method 之前,先回顧昨天所提到的 "查詢方法流程 (method lookup)"。
class Animal
def run
@str = "running"
end
end
class Cat < Animal
def speak
"meow"
end
end
kitty = Cat.new
kitty.run # => "running"
當 run() 方法被呼叫時, kitty 物件(receiver) 向右尋找 Cat 類別,如果沒有找到再繼續往上層找,直到 run() 方法被找到為止。
接者讓 Ruby 在 kitty 物件上定義一個新方法 scratch(), 如下面程式碼:
kitty = Cat.new
lucy = Cat.new
def kitty.scratch
"scratching"
end
kitty.scratch # => "scratching"
kitty.singleton_methods # => [:scratch]
lucy.scrach # => (NoMethodError)
如此一來,scratch() 就只能被 kitty 物件所使用,就算再建立新的實例物件 lucy 呼叫 scratch(),也只能得到錯誤訊息 (NoMethodError)。這個 scratch() 方法就稱為 singleton method。
我們知道『實例變數是住在實例物件裡面,而方法是住在類別 』,那 singleton method 是住在哪呢?
Singleton method 的所在位置並不是那麼明顯是有原因的,其實是在 Ruby 的世界裡,Object (物件) 是可以擁有自己的隱藏類別。這個隱藏類別就是 『 Singleton class 』,雖然也有其他的稱號,例如:anonymous class、eigenclass、metaclass 等…,但在 Ruby 原始碼上是稱為 singleton class。
加上 scratch()方法後,再看看查詢方法流程圖就應該如下圖:
要直接存取 singleton class 可用以下方法:
class << an_object # an_object是你要存取的Object
# 放你的程式碼
end
# Create singleton method at instance object level
kitty = Cat.new
class << kitty
def scratch
"scratching"
end
end
kitty.scratch # => "scratching"
kitty.singleton_methods # => [:scratch]
# Create singleton method at Class level
class << Cat
def scratch
"scratching"
end
end
Cat.scratch # => "scratching"
Cat.singleton_methods # => [:scratch]
最後可以到 rails console 裡看看,其實 rails 大量地使用 Singleton methods。
class << an_object # an_object是你要存取的Object
#放你的程式碼
end