背景:
以下是我对对象模型的理解(相对于我下面的问题):
> self始终引用当前堆栈帧中的接收器.
>当你处于顶级并且你说def someMethod时,隐式接收器是self,你正在创建一个位于与self关联的匿名类中的方法.这个匿名类恰好位于Object(self是Object类的一个实例)之下,因此当你调用someMethod时,Ruby“向右迈出一步”,它会进入匿名类,从而找到并调用你的方法.
>这类似于在类定义中定义方法时所发生的情况.如果,在类定义中,你说:def self.classMethod你正在一个匿名类中创建一个方法,它位于Class类的下面.此类的方法,当前正在定义的类的“右侧”将不会对新类的实例可见.
我的问题:
如何“在一个类中定义一个方法”首先发生? (语义上)
类对象不应该与普通对象不同,对吧?
根据我对消息处理的理解,Class对象有一个表作为其状态的一部分,可能意味着它是一个实例变量,它具有所有实例方法的名称.这是方法查找的工作方式. (如果Ruby没有找到它,它会一次又一次地上升,大概是链上下一个链接的方向是当前Class对象状态的一部分.)
由于Ruby并不真正关心对象类型,因此我认为它并不关心它在查找方法时特别关注Class对象.相反,它只是跟随引用并查找具有某些名称的状态位.那么,我可以创建自己的“类对象”而不使用不从Class类继承的class关键字吗?
如果那个问题没有任何意义,那么我道歉.我只是想知道解释器遇到def关键字时会发生什么.
最佳答案 当您在ruby中编写’def something’时,您正在向模块添加方法.有时该模块是“类”(一种模块).这完全取决于当时的“自我”:
class Foo
# right now self is 'Foo'
class << self
# right now self is 'Class:Foo'
end
def self.bar
# right now self is 'Foo'
end
end
def Foo.buz
# right now self is 'Foo'
end
obj = Foo.new
def obj.baz
# right now self is 'Foo:0x007fe8a632fa78' (an instance)
end
类只是一种模块.子类化是从一个模块到另一个模块创建指针的一种方法:
class Foo
end
class Bar < Foo
end
> Bar.ancestors
=> [Bar, Foo, Object, Kernel, BasicObject]
另一种方法是包括mixins:
module Mixin
end
class Foo
include Mixin
end
> Foo.ancestors
=> [Foo, Mixin, Object, Kernel, BasicObject]
方法调度适用于继承链中存在的内容.它是父模块的列表(不是树),并根据创建继承的时间进行排序:
# bar.rb
module MixinA
def something
puts "MixinA"
super
end
end
module MixinB
def something
puts "MixinB"
end
end
class Base
def something
puts "Base"
super
end
end
class Sub < Base
include MixinB
include MixinA
def something
puts "Sub"
super
end
end
obj = Sub.new
obj.something
跑:
$ruby bar.rb
Sub
MixinA
MixinB
检查链条:
> Sub.ancestors
=> [Sub, MixinA, MixinB, Base, Object, Kernel, BasicObject]
当遍历此列表中的方法调用时,查找相关方法.如果链中没有任何模块具有该方法,则搜索从顶部开始,而是调用method_missing.在任何一种情况下,第一个决议都获胜.
Yehuda Katz在2009年写了一篇关于这篇文章的好文章:
> http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/