为了账号安全,请及时绑定邮箱和手机立即绑定

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

标签:
Ruby


 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

©著作权归作者所有:来自51CTO博客作者blackanger的原创作品,如需转载,请注明出处,否则将追究法律责任

RubywebSingleton Class悟道集


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消