「Ruby」命名之爭 :singleton_class? meta_class? eigen_class?

  class << self; self; end

這段代碼,每個Rubyist應該都很熟悉。
但是這裏面的self是什麼? singleton_class? meta_class? eigen_class?

在早期,確切來說應該是Ruby1.9.2發佈之前,Ruby社區關於以上這段代碼的命名,有很大的爭議,後來Ruby團隊準備在1.9.2中增加一個方法,來消除這種命名的爭議。 這個名字除了Ruby官方的統一之外,更重要的是爲了方便Rubyist去使用。比如,1.9.2之前的代碼:


(class << self; self; end).class_eval do
define_method meth do |*args|
subject.send meth, *args
end
end


或者有更優雅的寫法:


def metaclass
class << self; self; end
end

metaclass.class_eval do
define_method meth do |*args|
subject.send meth, *args
end
end


這個metaclass是社區裏其中一個命名,還有命名爲eigen_class的, 在Ruby內部,被命名爲virtual class, 有代碼爲證:


#ruby 1.8.7  
class User
class << self
puts self
puts self.new
end
end
#=> #<Class:User>
#=> TypeError: can't create instance of virtual class


報錯的信息顯示,Ruby內部稱之爲:virtual class。

當然,在Ruby1.9.2之後, 確定了名字,叫做singleton_class, 代碼爲證:


class User
class << self
puts self
puts self.new
end
end
#=> #<Class:User>
#=> TypeError: can't create instance of singleton class


並且提供了一個方法,Object#singleton_class, 這是一個短形式,相當於你直接使用(class << self; self; end)


Object.instance_methods.grep(/class|singleton|eigen|meta/)
#=> [:class, :singleton_class, :singleton_methods, :define_singleton_method]


關於這個命名,社區裏還是有一些爭議的, 可以看這個帖子

有的人說用metaclass, metaclass翻譯成中文就是元類, 意思就是,一個類自己的類,但是明顯不符合事實,因爲在Ruby中,對於類還可以用這個命名,但是對象呢?每個對象都有這樣一個類(class << self; self; end), 自然,metaclass就被否決了。

有的人說用eigen_class,翻譯爲中文就是本質類,也可以叫固有類,有點偏語義、偏哲學層面,用這個名字其實也可以。但是,在Ruby裏已經有了一個方法,叫singleton_methods,專門用於查看eigen_class這樣的類中定義的方法, 難道要把singleton_methods改稱eigen_methods嗎? 或者叫eigenclass? eigenmethods? 就這樣Ruby核心團隊陷入了深深的困擾中。

其實最受歡迎的命名還是singleton_class, 但是這個命名有很大的歧義,那就是容易讓人聯想到設計模式 - 單例模式上面去。不知道這個設計模式的還好,知道這個設計模式的,第一印象就以爲是單例模式,尤其是國內,把singleton_class翻譯爲單例類讓人更加困擾,但實際上,這個singleton_class和單例模式沒有什麼關係, 我們只能從這個命名的英文含義去理解, 個人認爲中文翻譯爲單例類不太好,應該翻譯爲單類,因爲singleton_class是指Ruby中每個對象都對應的那個特殊的類,就像影子一樣跟着Ruby中的每一個對象,形單影隻,所以有人也把它叫做影子類。 所以,這些因素都是Ruby團隊需要考慮的。

但是最後的決定,還是用了singleton_class,因爲Ruby團隊不想去改已經實現的singleton_methods等帶着singleton_前綴的方法了。

這裏提一下,「Ruby元編程」中用的是eigenclass,作者說對於這個名字,官方並未定論,按理說在他寫這本書之前,應該1.9.2還未發佈,但是2011年這本書出版的時候,Ruby1.9.2應該早出版了,singleton_class應該就是官方對於(class << self; self; end)的定論了。

值得一提的是,Ruby標準庫裏有一個Singleton Moudle,這個纔是真正用於去實現單例模式的。

那麼現在,我們要動態的創建一個類或對象的方法,可以方便的去使用singleton_class了:


singleton_class.class_eval do
define_method meth do |*args|
subject.send meth, *args
end
end


關於singleton class的更多示例:


class User
def self.name
puts "hello"
end

class << self
def age
puts "18 years old"
end
end
end

User.singleton_methods #=> [:name, :age]

user = User.new
def user.lover
puts "kitty"
end
user.singleton_methods #=> [:lover]

other_user = User.new
other_user.singleton_methods #=> []

class Admin < User
end
Admin.singleton_methods #=> [:name, :age]


其實關於Singleton Class這樣的對象模型設計,是屬於Ruby語言首創。至於Ruby語言爲什麼這樣設計? 我們以後再談。


如果你喜歡本文,想看更多內容,請關注微信公衆平臺:RubyStudy


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章