您好,登錄后才能下訂單哦!
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]
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。