Ruby中的单例类本身就是类吗?这是所有对象都属于“类”的原因吗?这个概念很模糊,但是我认为它与为什么我可以完全定义类方法有关(class foo; def foo.bar ...
)。
Ruby中的单例类是什么?
Answers:
首先,一个简单的定义:单例方法是仅针对单个对象定义的方法。例:
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 << 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
Ruby提供了一种定义特定于特定对象的方法的方法,这种方法称为Singleton方法。当在对象上声明单例方法时,Ruby会自动创建一个仅容纳单例方法的类。新创建的类称为Singleton类。
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类是特定于对象的匿名类,它会自动创建并插入到继承层次结构中。
singleton_methods
可以在对象上调用以获得对象上所有单例方法的名称列表。
foo.singleton_methods # => [:size]
bar.singleton_methods # => []
这篇文章确实帮助我了解了Ruby中的Singleton类,并提供了一个很好的代码示例。
刚更新为@Pistos答案时,从1.9.2版本的ruby添加新语法到获取单例类
singleton_class = ( class << foo; self; end )
可以替换为:
singleton_class = foo.singleton_class
最实用/行动主义的思考方式(IMHO)是:作为继承链,或方法查找/解析顺序。这张照片可能会有所帮助
http://www.klankboomklang.com/2007/11/25/modules-part-i-enter-the-include-class/
这是1.9版,对比了内置类和用户定义类:我仍在消化这个类。
http://d.hatena.ne.jp/sumim/20080111/p1
另外,我认为该术语的混淆用法是“单个对象”,这是不同的概念。单例对象来自一个类,该类的构造函数/实例化方法被覆盖,因此您只能分配该类中的一个。
用最简单的术语来说,单例类是特殊类的红宝石鞭子,用于承载在单个对象上定义的方法。在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>>
您还可以通过使用method对象找出定义了“ age”方法的位置,在这里询问ruby是否找到“ 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