Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何';定义一种方法';在语义上工作? 背景:_Ruby_Class_Object_Methods_Object Model - Fatal编程技术网

Ruby 如何';定义一种方法';在语义上工作? 背景:

Ruby 如何';定义一种方法';在语义上工作? 背景:,ruby,class,object,methods,object-model,Ruby,Class,Object,Methods,Object Model,以下是我对对象模型的理解(相对于我下面的问题): self始终引用当前堆栈帧中的接收器 当您处于顶层并说def someMethod时,隐式接收器是self,您正在创建一个与self关联的匿名类中的方法。这个匿名类恰好位于对象的下方(self是对象类的一个实例),因此当您调用someMethod时,Ruby“向右迈出一步”,它进入匿名类,从而找到并调用您的方法 这类似于在类定义中定义方法时发生的情况。如果在类定义中,您说:def self.classMethod您正在一个匿名类中创建一个方法,

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

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

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

Class
对象不应该与普通对象不同,对吗

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

由于Ruby并不真正关心对象类型,所以我认为它不关心在执行方法查找时是否特别在
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
方法分派处理继承链中存在的内容。它是父模块的列表(不是树),并根据创建继承的时间进行排序:

# 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
检查链条:

> Sub.ancestors
=> [Sub, MixinA, MixinB, Base, Object, Kernel, BasicObject]
当此列表中发生方法调用时,将查找有问题的方法。如果链中没有一个模块具有该方法,则搜索从顶部开始,而是调用方法\u missing。在任何一种情况下,找到的第一个解决方案都将获胜

Yehuda Katz在2009年写了一篇关于这方面的好文章:


不从
类继承的类对象是什么?这不是其他物体吗?@DaveNewton是的。这就是为什么我用双引号引它。我问你是否可以创建一个行为类似于
对象的普通对象,并隐含地问这样做会涉及到什么。。。。。同样,这只是为了理解“定义方法”的真正含义,您可以使用
class.new(superclass=nil)创建类对象
如果您检查
Class.new.Class.superclass
您可以确定
Class
继承自-这是它获得大部分功能的地方。如果您真的想要,您很可能会扩展
模块来创建类似类的对象。
# 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]