ruby - 'defining a method' 在语义上是如何工作的?

标签 ruby class object methods object-model

背景:

这是我对对象模型的理解(相对于我下面的问题):

  • self始终引用当前堆栈帧中的接收器。
  • 当你在顶层时说 def someMethod隐式接收者是 self并且您正在创建一个位于与 self 关联的匿名类中的方法.这个匿名类恰好位于 Object 下面( selfObject 类的一个实例)所以当你调用 someMethod 时,Ruby“向右走了一步”,它落在了匿名类中,从而找到并调用了你的方法。
  • 这类似于在类定义中定义方法时发生的情况。如果在类定义中,您说:def self.classMethod您正在一个位于 Class 正下方的匿名类中创建一个方法类(class)。此类的方法,当前正在定义的类的“右侧”现有方法将对新类的实例不可见。

我的问题:

“在类中定义方法”首先是如何发生的?(语义上)

Class对象不应该与普通对象不同,对吧?

根据我对消息处理的理解,Class对象有一个表作为其状态的一部分,这可能意味着它是一个实例变量,具有其所有实例方法的名称。这就是查找方法的工作原理。 (如果 Ruby 没有找到它,它会一次又一次地上升,大概到链上的下一个链接的方向是当前 Class 对象状态的一部分。)

由于 Ruby 并不真正关心对象类型,我认为它并不关心它在 Class 中查找。特别是在进行方法查找时的对象。相反,它只是跟随引用并寻找具有特定名称的状态位。那么,我可以创建自己的“类对象”而不使用不从 Class 继承的 class 关键字吗?类(class)?

如果这个问题没有任何意义,那么我深表歉意。我只想知道解释器遇到 def 时会发生什么关键字

最佳答案

当您在 ruby​​ 中编写“def something”时,您是在向模块添加方法。有时该模块是一个“类”(一种模块)。这完全取决于当时的“ 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

类只是一种模块。子类化是创建从一个模块到另一个模块的指针的一种方法:

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]

方法分派(dispatch)适用于继承链中存在的内容。它是父模块的列表(不是树),并根据创建继承的时间排序:

# 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 年写了一篇关于这个东西的好文章:

关于ruby - 'defining a method' 在语义上是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29929656/

相关文章:

Java:关于对象的概念

c++ - c++中对象的初始化

ruby-on-rails - 多部分表单在 Rails 中不起作用

ruby-on-rails - Rails 3. HABTM 表单选择下拉菜单

ruby - Watir-Webdriver 如何处理加载失败的页面并继续测试

javascript - 如何在 Node.js 中设置和访问类属性?

ruby - Chef : should I be checking "syntaxcache" files into version control?

c++ - () = 类中的运算符重载

python - 在Python中访问基类原始类型

javascript - 在 JavaScript 中使用递归更新嵌套的 json 对象