90

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

Ruby 中的单例类是什么?

4

5 回答 5

160

首先,一点定义:单例方法是只为单个对象定义的方法。例子:

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

You open the singleton class of an object with the syntax class << obj. Here, we see that this singleton class is where the singleton methods are defined:

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

So an alternative means of adding singleton methods to an object would be to define them with the object's singleton class open:

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

In summary:

  • methods must always belong to a class (or: be instance methods of some class)
  • normal methods belong to the class they're defined in (i.e. are instance methods of the class)
  • class methods are just singleton methods of a Class
  • singleton methods of an object are not instance methods of the class of the object; rather, they are instance methods of the singleton class of the object.
于 2008-10-17T18:01:00.403 回答
36

Ruby provides a way to define methods that are specific to a particular object and such methods are known as Singleton Methods. When one declares a singleton method on an object, Ruby automatically creates a class to hold just the singleton methods. The newly created class is called 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 class is object specific anonymous class that is automatically created and inserted into the inheritance hierarchy.

singleton_methods can be called on an object to get the list of of names for all of the singleton methods on an object.

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

This article really helped me to understand Singleton Classes in Ruby and it has a good code example.

于 2012-01-19T20:21:16.563 回答
7

As just update to @Pistos answer, from version 1.9.2 ruby add new syntax to getting singleton class

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

can be replaced with:

singleton_class = foo.singleton_class

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

于 2017-10-24T17:42:54.953 回答
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

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

于 2008-10-17T16:49:06.913 回答
1

A singleton class in the simplest terms is a special class ruby whips up to host methods defined on individual objects. In ruby, it is possible to define methods on individual objects that are unique to that object alone. For instance consider the following below

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>)

As you can see above, user1 object does not respond to the 'age' method because it is a singleton method, a method uniquely defined on user object. For this to happen, ruby creates a special class, called singleton class, or eigenclass, to host this unique method. You can verify this by doing the following:

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

You can also ask ruby whether the 'age' method is found here by using the method object to find out where the method 'age' is defined. When you do this you will see that singleton class has that method.

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]

Also note that, as far a singleton class goes, singleton methods are actually it's instance methods.

user.singleton_methods == user_singleton_class.instance_methods(false) # true
于 2020-02-29T18:26:56.857 回答