Everything in Ruby is an Object

1

Ruby 允许给单个对象增加方法,方法添加后只对该对象生效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# foo 是 String 类的对象
foo = 'bar'

# 给 foo 添加单例方法 bar,只存在在 foo 中
def foo.bar
puts 'this is foobar'
end

# 在 foo 上调用 bar 方法成功
foo.bar # => 'this is foobar'

# 在另一个字符串上调用失败
'foobar'.bar #=> NoMethodError

# 证明 bar 确实是 foo 的单件方法
foo.singleton_methods #=> [:bar]

2

Ruby 允许给类添加类方法,方法添加后只对该类生效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 定义类方法的第一种方式
class Foo
def self.bar
'foobar'
end
end

Foo.bar # => 'foobar'

# 定义类方法的第二种方式
class Foo
class << self
def bar
'foobar'
end
end
end

Foo.bar # => 'foobar'

3

Ruby 中一切皆是对象

类也是对象

所有类都是 Class 类的对象

#2 中的 Foo 类,也是 Class 类的对象,给 Foo 添加的类方法在其他 Class 的对象中不存在

1
2
3
4
5
# 同为 Class 的对象,String 却没有 bar 方法
String.bar # => NoMethodError

# bar 只是 Foo 的单例对象
Foo.singleton_methods # => [:bar]

#2 中给类 Foo 添加的类方法,就像给 #1 中给对象 foo 添加的方法一样

添加的都是单例方法

所以所谓的类方法,其实就是类对象的单例方法

只不过 #1 和 #2 它们作用在不同的对象上而已

1
2
3
4
5
6
7
8
9
# 证明 bar 确实是 Foo 类的单例方法(类方法)
Foo.singleton_methods # => [:bar]

# 换种方式定义类方法就显而易见了
def Foo.bar
'foobar'
end

Foo.bar # => 'foobar'

如果对象是个实例对象,添加的方法就是他的单件方法

如果对象是个类,添加的方法就是这个类的类方法

4

Ruby 中查找方法遵循“向右一步,再向上”

先向右一步查找实例对象所属的类是否存在该方法,再向上查找该类的祖先类是否存在该方法

而单例方法并不定义在类中(否则所以实例对象都能共享)

所以单例方法存在在 ghost 里,这个 ghost 位于对象和类之间

这个 ghost 又被称作单例类,或单件类(singleton class)

5

单例类位于类和实例之间,像个幽灵,但是利用 class << obj 语法可以打开 obj 所属的单例类

比如 #2 的 Foo

1
2
3
4
5
6
7
8
9
10
11
class Foo; end

# 进入到 Foo 的单例类并定义一个方法 bar
class << Foo
def bar
'foobar'
end
end

# bar 成了 Foo 的类方法
Foo.bar # => 'foobar'

再比如 #1 中的实例对象 foo

1
2
3
4
5
6
7
8
9
10
foo = 'bar'

# 打开 foo 所属的单例类
class << foo
def bar
'foobar'
end
end

foo.bar # => 'foobar'

6

Ruby 的对象模型相当简洁,归根结底在于一切皆对象,本质上来说没有类方法和实例方法,只有属于对象的方法

Simple is hard