gpt4 book ai didi

ruby - ruby 方法查找中的*实际*步骤是什么?

转载 作者:数据小太阳 更新时间:2023-10-29 07:08:03 27 4
gpt4 key购买 nike

我已经阅读了有关此主题的 stackoverflow 帖子以及包括 A Primer on Ruby Method Lookup 在内的几篇文章, What is the method lookup path in Ruby .此外,我查看了Ruby Metaprogramming 2 中的对象模型章节,在几个聊天室中询问,并做了this reddit thread。 .除了学习 C,我已经尽我所能来解决这个问题。

如上述资源所述,这 6 个位置在接收对象(如 fido_instance)的方法查找期间(按顺序)被检查。 :

  1. fido_instance 的单例类
  2. IClass(来自扩展模块)
  3. IClass(来自前置模块)
  4. IClass(来自包含的模块)
  5. 父类(super class)(如果这里没有找到方法,重复步骤 4-6)

显然,该图并不完整,所有这些单例类可能都不是在现实世界中创建的。尽管如此,这 6 个步骤仍有很多不足之处,并且不涵盖以下场景。如果fido_instance单例类之上没有extended/prepended IClass,那么就没有说明第4步是否在fido_instance单例类上执行。我不得不假设不会,因为整个方法查找会短路。

如果我要猜测一组可以解释 ruby​​ 的方法查找行为的步骤,它可能看起来像:

  1. 检查 fido_instance.class 方法。 (显然,ruby 不会使用它自己的#class 方法来进行方法查找,但它传达了流程的逻辑)
  2. 检查 fido_instance.class.superclass 方法。继续添加 .superclass 并检查方法,直到没有父类(super class)为止。 (同样,ruby 不会使用它自己的#superclass 方法)
  3. 未找到方法。从第 1 步开始,这次寻找#method_missing。

我还记得读过如果接收对象是类,则有一个单独的方法查找过程,但我不记得在哪里。

那么不涉及了解 C 的正确、详细的解释是什么?

最佳答案

我认为在第二个引用文献中有一个…… gem ……触及了答案的核心:单例类的祖先。应用于您的对象,它将是:

fido_instance.singleton_class.ancestors

这将始终为您提供 Ruby 使用的方法查找顺序。当您以这种方式查看它时,它非常简单,这就是您问题的底线答案。 Ruby 将从 singleton_class 开始,向上寻找该方法的祖先。使用您的图表:

fido.singleton_class.ancestors
=> [Fetch, WagTail, DogClass, Object, Kernel, BasicObject]

(注意 1:Bark 不是此输出的一部分,因为您使用了 extend 而不是 include。稍后会详细介绍。)

(注意 2:如果一直到 BasicObject 都没有找到它,那么它会在同一个祖先链上调用 method_missing。)

在类上调用方法没有什么不同,因为在 Ruby 中,类只是 Class 类的一个实例。所以 DogClass.method1 将在 DogClass.singleton_class 上搜索 method1,然后向上搜索它的祖先链,就像以前一样。

DogClass.singleton_class.ancestors
=> [Bark, Class, Module, Object, Kernel, BasicObject]

由于您对 Bark 使用了 extend,所以我们可以在这里找到它!因此,如果 Bark 定义了方法 bark,那么您可以调用 DogClass.bark,因为该方法是在 DogClass 中定义的'singleton_class' 的祖先。

要了解祖先树是什么(而不是每次都打印出来),您只需要知道祖先是如何通过子类化、extendinclude前置

  1. 子类化为子类提供了其父类(super class)的整个祖先链。
  2. includeC 中的模块将该模块添加到祖先链中 C 之后和其他所有内容之前。
  3. prependC 中的模块将该模块添加到祖先链中的所有内容之前,包括 C 和任何当前预先添加的模块。
  4. def x.method1method1 添加到 x.singleton_class。类似地,x.extend(M) 会将 M 添加到 x.singleton_class 的祖先(但不会添加到 x.class)。请注意,后者正是 BarkDogClass.singleton_class 发生的情况,但同样适用于任何对象。

从上面的列表中省略 extend,因为它不会修改对象的祖先链。它确实修改了该对象的 singleton_class 的祖先——正如我们所见,Bark 包含在 DogClass.singleton_class.ancestors 中。


切线:

上面关于类方法的部分是我理解单例类对 Ruby 的重要性的关键。你显然不能在 DogClass.class 上定义 bark,因为 DogClass.class == Class 而我们不想要 bark Class 上!那么我们如何才能让 DogClass 成为 Class 的一个实例,让它拥有一个为 定义的(类)方法 bark >DogClass 但不是不相关的类?使用单例类!通过这种方式,在类 C 中通过 def self.x 定义“类方法”有点像 C.singleton_class.send(:define_method , :x) {...}.

关于ruby - ruby 方法查找中的*实际*步骤是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50286933/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com