我们可能了解Ruby的singleton method概念,它指的是一个对象独有的方法。
下面举个简单的例子,首先来定义一个类:
class ExampleClass
def foo
puts 'foot'
end
end
然后创建两个实例,并且给第二个实例增加一个singleton method:
example1 = ExampleClass.new
example2 = ExampleClass.new
def example2.bar
puts 'bar'
end
example2.bar
它的输出结果是:
"bar"
而从下面这个结果我们可以看到,example1并不具有bar这个方法:
example1.bar #=> undefined method 'bar' for ... (No Method Error)
这就是所谓的singleton method。
我们还可以通过另外一种方式给example2定义一个singleton method:
class << example2
def bar
puts 'bar'
end
end
那Ruby是如何实现singleton method的呢?
当我们为一个特定的对象定义一个方法时,在对象和它的“真正类”之间会插入一个新的匿名类,而这个singleton method会定义在这个类中。所以,当我们调用bar方法时,解释器首先会在这个匿名类中寻找方法的定义,然后才会去“真正的类”ExampleClass那里去寻找。在Ruby里面,把这个匿名类称之为“singleton class
”或者“shadow class”。
让我们来看一下这个singleton class到底是什么:
puts example2.class
class << example2
puts self
end
输出结果:
ExampleClass
#<Class:#<ExampleClass:0x28305d>>
可以看到,bar方法定义所在的类的的确确并不是ExampleClass,而是一个匿名类。
类方法
在Ruby中,我们往往可以通过以下几种方式给一个类定义一个类方法:
class ClassMethodExample
def self.foo
puts 'class foo'
end
class << self
def bar
puts 'class bar'
end
end
end
class << ClassMethodExample
def baz
puts 'class baz'
end
end
def ClassMethodExample.tor
puts 'class tor'
end
ClassMethodExample.foo
ClassMethodExample.bar
ClassMethodExample.baz
ClassMethodExample.tor
输出结果为:
"class foo"
"class bar"
"class baz"
"class tor"
看了这种定义方式,是否发现它和给一个对象增加一个singleton method的方式很相似呢?
没错,其实他们就是一样的。在Ruby里面,一个类是一个实例,是类Class的一个实例
。那我们就很好理解这两种方式的一致性:给类增加一个类方法,不就是往“类”这个实例中增加一个singleton method么?
还是让我们来看看Ruby的对象模型
吧:

(图1:Ruby的对象模型)
上图中绿色代表”普通“类,蓝色代表meta-class。虚线代表类与对象间的关系(instance of),箭头指向的方向为”类的方向“。实线代表继承关系,箭头指向的方向为“父类”方向。
上例中的ExampleClass只是上图中所指的“普通类”Class的一个实例,可以通过下面的方法印证:
puts ExampleClass.new.class
puts ExampleClass.class
输出:
"ExampleClass"
"Class"
而相对于ExampleClass而言,类Class就是它的meta-class
。
所有的”最低级类“都是类Class的实例?没错。实际上,我们需要注意一点:类名是一个常量
。比如当我们调用ExampleClass.new时,我们实际上是向一个Class类的实例发送消息,而类名这个常量指向的就是这个实例。
再来看看,ClassMethodExample类中的类方法,实际上就是这个Class类实例的singleton method,它们也存在于这个实例的singleton class中:
puts ClassMethodExample.instance_methods.inspect
puts ClassMethodExample.class.instance_methods.inspect
class << ClassMethodExample
puts self.instance_methods.inspect
end
输出结果:
"['methods', 'freeze', ...]"
"['new', 'allocate', ...]"
"['bar', 'tor', ...]"
完毕。
Reference:
http://olabini.com/blog/tag/singleton-class/
http://www.hokstad.com/ruby-object-model.html
http://www.rubycentral.com/book/tut_classes.html

- 大小: 49.1 KB
分享到:
- 2009-08-08 21:11
- 浏览 1366
- 评论(1)
- 论坛回复 / 浏览 (-1 / 2035)
- 查看更多
相关推荐
Ruby中的每个类都拥有一个对应的元类(也称为eigenclass或singleton class),这是实现元编程的关键结构,因为元类允许我们在运行时给类动态地添加方法和属性。 Ruby的元编程能力在Rails框架中得到了广泛的应用。...
通过使用`singleton_class`和`instance_variable_set`方法,我们可以创建并控制单例对象。 2. **工厂模式**:在Rails中,ActiveRecord的`build`和`create`方法就是工厂方法的例子。它们负责创建和保存模型实例。...
Ruby是一种动态类型的面向对象语言,它的灵活性和简洁性使得它非常适合进行元编程。元编程是指编写能够生成或操纵其他代码的程序的技术。在Ruby中,元编程是一项非常强大的特性,可以让开发者以更加灵活的方式构建...
Ruby是一种动态、面向对象的脚本语言,以其简洁、优雅的语法和强大的元编程能力著称。在第二版中,作者深入浅出地讲解了Ruby的核心概念和特性,帮助读者建立起坚实的编程基础。 本书的知识点涵盖了以下几个方面: ...
Ruby的核心特性之一是其强大的面向对象编程模型。在Ruby中,一切皆为对象,包括基本类型如整数、字符串和布尔值。它提供了类、模块、继承、封装、多态等概念,使得代码更加模块化和易于维护。书中会详细讲解如何定义...
9. **类方法和单例方法(Class Methods and Singleton Methods)**:类方法是直接定义在类上的方法,而单例方法则是为特定对象定义的方法,每个对象都有自己的单例类。 10. **Gem生态系统(Gem Ecosystem)**:Ruby...
Ruby是一种强大的面向对象编程语言,以其简洁、优雅的语法和高度的灵活性著称。在软件开发中,设计模式是解决常见问题的可重用解决方案,它们代表了在特定上下文中被广泛接受的最佳实践。Ruby虽然相对年轻,但其丰富...
1. **确保唯一实例**:一个类在整个应用中只存在一个实例。 2. **自我创建实例**:由类自身负责创建并管理该唯一实例。 3. **提供全局访问点**:通常通过一个静态方法或者特定的方法来实现对这个唯一实例的访问。 #...