'defining a method' 在语义上是如何工作的?
How does 'defining a method' work semantically?
背景:
以下是我对对象模型的理解(相对于我在下面的问题):
self
总是引用当前栈帧中的接收者。
- 当你在顶层并且你说
def someMethod
隐式接收者是 self
并且你正在创建一个方法,它位于与 [=11 关联的匿名 class 中=].这个匿名 class 正好位于 Object
下方(self
是 Object
class 的一个实例)所以当你调用 someMethod
时,Ruby "takes a step to the right",它落在匿名 class 中,从而找到并调用您的方法。
- 这类似于在 class 定义中定义方法时发生的情况。如果在 class 定义中,您说:
def self.classMethod
您正在创建匿名 class 中的方法,它位于 Class
class 的正下方。当前正在定义的 class 的 class 的现有 "to the right" 方法对新 class 的实例不可见。
我的问题:
"defining a method in a class" 首先是如何发生的?(语义上)
Class
物体不应该与普通物体不同,对吧?
根据我对消息处理的理解,Class
对象有一个 table 作为其状态的一部分,大概意味着它是一个实例变量,具有其所有实例的名称方法。这就是查找方法的工作原理。 (如果 Ruby 没有找到它,它会一次又一次地上升,大概指向链上的下一个 link 的方向是当前 Class
对象状态的一部分。 )
由于 Ruby 并不真正关心对象类型,我认为它并不关心它在进行方法查找时专门查找 Class
对象。相反,它只是跟随引用并寻找具有特定名称的状态位。那么,我可以创建自己的 "class objects" 而不使用不从 Class
class 继承的 class 关键字吗?
如果这个问题没有任何意义,那么我深表歉意。我只想知道当解释器遇到def
关键字时会发生什么。
当您在 ruby 中编写 'def something' 时,您正在向模块添加方法。有时该模块是 'class'(一种模块)。这完全取决于当时 'self' 是什么:
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
A class 只是一种模块。 Subclassing 是一种创建从一个模块到另一个模块的指针的方法:
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]
当方法调用发生时,将遍历此列表以查找有问题的方法。如果链中的 none 个模块具有该方法,则搜索从顶部开始,而是调用 method_missing。在任何一种情况下,找到的第一个解决方案都会获胜。
Yehuda Katz 在 2009 年写了一篇关于这个东西的好文章:
背景:
以下是我对对象模型的理解(相对于我在下面的问题):
self
总是引用当前栈帧中的接收者。- 当你在顶层并且你说
def someMethod
隐式接收者是self
并且你正在创建一个方法,它位于与 [=11 关联的匿名 class 中=].这个匿名 class 正好位于Object
下方(self
是Object
class 的一个实例)所以当你调用someMethod
时,Ruby "takes a step to the right",它落在匿名 class 中,从而找到并调用您的方法。 - 这类似于在 class 定义中定义方法时发生的情况。如果在 class 定义中,您说:
def self.classMethod
您正在创建匿名 class 中的方法,它位于Class
class 的正下方。当前正在定义的 class 的 class 的现有 "to the right" 方法对新 class 的实例不可见。
我的问题:
"defining a method in a class" 首先是如何发生的?(语义上)
Class
物体不应该与普通物体不同,对吧?
根据我对消息处理的理解,Class
对象有一个 table 作为其状态的一部分,大概意味着它是一个实例变量,具有其所有实例的名称方法。这就是查找方法的工作原理。 (如果 Ruby 没有找到它,它会一次又一次地上升,大概指向链上的下一个 link 的方向是当前 Class
对象状态的一部分。 )
由于 Ruby 并不真正关心对象类型,我认为它并不关心它在进行方法查找时专门查找 Class
对象。相反,它只是跟随引用并寻找具有特定名称的状态位。那么,我可以创建自己的 "class objects" 而不使用不从 Class
class 继承的 class 关键字吗?
如果这个问题没有任何意义,那么我深表歉意。我只想知道当解释器遇到def
关键字时会发生什么。
当您在 ruby 中编写 'def something' 时,您正在向模块添加方法。有时该模块是 'class'(一种模块)。这完全取决于当时 'self' 是什么:
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
A class 只是一种模块。 Subclassing 是一种创建从一个模块到另一个模块的指针的方法:
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]
当方法调用发生时,将遍历此列表以查找有问题的方法。如果链中的 none 个模块具有该方法,则搜索从顶部开始,而是调用 method_missing。在任何一种情况下,找到的第一个解决方案都会获胜。
Yehuda Katz 在 2009 年写了一篇关于这个东西的好文章: