Ruby和元编程之万物皆为对象

2019-09-25 09:47:50王冬梅

Ruby中,当我们在方法调用的运行时,对象会查找他隶属的类,module,父类等,来找到相对应的方法。

Singleton/Meta/Anonymous/Ghost/Shadow Class

1.Singleton Class: 单例类
2.Meta Class:元类
3.Anonymous Class: 匿名类
4.Ghost Class:鬼类
5.Shadow Class: 影子类

上面的这些东东其实说的都是一个东西,我喜欢叫它 影子类。

Ruby中每一个对象都一个一个影子类,这个影子类存在于对象跟它所属的类之间:

对象("obj1") -> 影子类 -> 对象所属的类(String)

当一个对象的方法被调用时,首先查找的是影子类,之后才是它所属的类。

上面讲到实例变量存在于对象内,方法存在于对象的类中。
影子类上的方法,就是只有这一个对象拥有的方法。这个方法通常叫做单例方法(Singleton Method)。

这样的方法只存在于这个对象上,同一个类的其他对象没有这个方法,因为他们的影子类不同,其他对象的影子类上没有这个方法。


>> a = "obj1"
=> "obj1"
>> def a.hello
>> puts "hello world"
>> end
=> nil
>> a.hello
hello world
=> nil
>> b = "obj2"
=> "obj2"
>> b.hello
NoMethodError: undefined method `hello' for "obj2":String
    from (irb):49
>> a.singleton_methods
=> ["hello"]
>> b.singleton_methods
=> []

Self

Ruby里面一切都是对象,self也是对象,确切地说是当前对象的引用。

前文说Ruby的方法调用是消息模式,比如obj.method, 消息的接受者是.之前的对象,.之后的是方法及参数。
如果对象和.没有出现的话,消息会被默认送到self对象。除了作为方法的默认接受者,self也是实例变量的解析对象。

self在ruby一开始的时候,被设定为一个叫做main的对象,再irb里面可以看到:

>> m = self
=> main

self可以被认为是一个特殊的变量,它的特殊性在于,你不能给他赋值:

>> self = "obj"
SyntaxError: compile error
(irb):77: Can't change the value of self
self = "obj"
      ^

有几个办法可以改变self的值,.(obj.method的.)是其中一个,除了.还有class/module关键字。
本回主要关注跟对象相关的.

当我们用obj.method调用方法时,接下来的时间代码的执行就会到相应的方法里,运行的上下文切换到那个对象,self自然也变成了那个对象。用def定义单例方法时,道理也是相通的。 下面的例子可以说明这个self切换的情况。

>> a = "obj"
=> "obj"
>> def a.hello_self