ruby 中的单例类到底是啥?

Posted

技术标签:

【中文标题】ruby 中的单例类到底是啥?【英文标题】:What exactly is the singleton class in ruby?ruby 中的单例类到底是什么? 【发布时间】:2010-09-17 18:21:24 【问题描述】:

Ruby 中的单例类本身就是一个类吗?这就是所有对象都属于“类”的原因吗?这个概念是模糊的,但我相信这与我为什么可以定义一个类方法有关 (class foo; def foo.bar ...)。

Ruby 中的单例类是什么?

【问题讨论】:

【参考方案1】:

首先,稍微定义一下:单例方法是只为单个对象定义的方法。示例:

irb(main):001:0> class Foo; def method1; puts 1; end; end
=> nil
irb(main):002:0> foo = Foo.new
=> #<Foo:0xb79fa724>
irb(main):003:0> def foo.method2; puts 2; end
=> nil
irb(main):004:0> foo.method1
1
=> nil
irb(main):005:0> foo.method2
2
=> nil
irb(main):006:0> other_foo = Foo.new
=> #<Foo:0xb79f0ef4>
irb(main):007:0> other_foo.method1
1
=> nil
irb(main):008:0> other_foo.method2
NoMethodError: undefined method `method2' for #<Foo:0xb79f0ef4>
        from (irb):8

实例方法是类的方法(即在类的定义中定义)。类方法是类的Class 实例上的单例方法——它们没有在类的定义中定义。相反,它们是在对象的单例类上定义的。

irb(main):009:0> Foo.method_defined? :method1
=> true
irb(main):010:0> Foo.method_defined? :method2
=> false

您使用语法class &lt;&lt; obj 打开对象的单例类。在这里,我们看到这个单例类是定义单例方法的地方:

irb(main):012:0> singleton_class = ( class << foo; self; end )
=> #<Class:#<Foo:0xb79fa724>>
irb(main):013:0> singleton_class.method_defined? :method1
=> true
irb(main):014:0> singleton_class.method_defined? :method2
=> true
irb(main):015:0> other_singleton_class = ( class << other_foo; self; end )
=> #<Class:#<Foo:0xb79f0ef4>>
irb(main):016:0> other_singleton_class.method_defined? :method1
=> true
irb(main):017:0> other_singleton_class.method_defined? :method2
=> false

因此,向对象添加单例方法的另一种方法是在打开对象的单例类的情况下定义它们:

irb(main):018:0> class << foo; def method3; puts 3; end; end
=> nil
irb(main):019:0> foo.method3
3
=> nil
irb(main):022:0> Foo.method_defined? :method3
=> false

总结:

方法必须始终属于一个类(或者:是某个类的实例方法) 普通方法属于定义它们的类(即是类的实例方法) 类方法只是Class 的单例方法 对象的单例方法不是对象类的实例方法;相反,它们是对象的单例类的实例方法。

【讨论】:

我的墓碑上会写着“RIP Ruby Singleton。皮斯托斯拯救了我的理智。” @sawa 我很欣赏你编辑的意图,但我觉得他们改变了我帖子的含义和交流有点太多了,所以我回滚了你的编辑。【参考方案2】:

Ruby 提供了一种方法来定义特定于特定对象的方法,这些方法称为单例方法。当在对象上声明单例方法时,Ruby 会自动创建一个类来仅保存单例方法。新创建的类称为 Singleton Class。


    foo = Array.new
    def foo.size
      "Hello World!"
    end
    foo.size  # => "Hello World!"
    foo.class # => Array
    #Create another instance of Array Class and call size method on it
    bar = Array.new
    bar.size  # => 0
单例类是对象特定的匿名类,它会自动创建并插入到继承层次结构中。

可以在对象上调用singleton_methods 以获取对象上所有单例方法的名称列表。

    foo.singleton_methods  # => [:size]
    bar.singleton_methods  # => []

article 确实帮助我理解了 Ruby 中的单例类,它有一个很好的代码示例。

【讨论】:

虽然这个答案已经有一年多了,而且这个链接很有帮助,但是如果你在这个网站上发布答案的基本部分会更好,或者你的帖子有被删除的风险See the FAQ where it mentions answers that are 'barely more than a link'.你如果您愿意,仍然可以包含该链接,但仅作为“参考”。答案应该是独立的,不需要链接。 在这里同意@bluefeet 感谢@bluefeet,更新了答案以解决您的评论。 这是最清楚的答案【参考方案3】:

刚刚更新到@Pistos 答案,从 1.9.2 版 ruby​​ 添加新语法以获取单例类

 singleton_class = ( class << foo; self; end )

可以替换为:

singleton_class = foo.singleton_class

https://apidock.com/ruby/Object/singleton_class

【讨论】:

【参考方案4】:

最务实/以行动为导向的思考方式(恕我直言)是:作为继承链,或方法查找/解析顺序。这张照片可能会有所帮助

http://www.klankboomklang.com/2007/11/25/modules-part-i-enter-the-include-class/

这是 r 1.9,对比内置和用户定义的类:我还在消化这个。

http://d.hatena.ne.jp/sumim/20080111/p1

另外,我认为这个术语的一个令人困惑的用法是“单例对象”,这是一个不同的概念。单例对象来自一个类,该类的构造函数/实例化方法被重写,因此您只能分配该类中的一个。

【讨论】:

其中一个链接已失效。另一个是日本人!【参考方案5】:

用最简单的术语来说,一个单例类是一个特殊的类,ruby 鞭打在单个对象上定义的宿主方法。在 ruby​​ 中,可以在单个对象上定义仅对该对象唯一的方法。例如考虑以下内容

class User; end
user = User.new
def user.age
  "i'm a unique method"
end
user1 = User.new 
user.age #"i'm a unique method"
user1.age # NoMethodError (undefined method `age' for #<User:0x0000559c66ab7338>)

正如您在上面看到的,user1 对象不响应 'age' 方法,因为它是一个单例方法,一个在用户对象上唯一定义的方法。为此,ruby 创建了一个特殊的类,称为单例类或特征类,来承载这个独特的方法。您可以通过执行以下操作来验证这一点:

user.singleton_class # #<Class:#<User:0x0000559c66b47c58>>

你也可以通过使用方法对象来询问ruby是否找到'age'方法在这里找到方法'age'定义的地方。当你这样做时,你会看到单例类有那个方法。

user_singleton_class = user.method(:age).owner # #<Class:#<User:0x0000559c66b47c58>>
user.method(:age).owner == user.singleton_class # true
user_singleton_class.instance_methods(false) # [:age]

还要注意,就单例类而言,单例方法实际上是它的实例方法。

user.singleton_methods == user_singleton_class.instance_methods(false) # true

【讨论】:

以上是关于ruby 中的单例类到底是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin 中的单例类

目标c中的单例类

swift中的单例类变量? [复制]

在打开的单例类中调用单例类方法

实现接口的单例类[重复]

Ruby中的类和该类的单例有啥区别?