我读过关于这一主题的帖子计算器以及几篇文章,其中包括入门Ruby的方法查找,什么是Ruby的方法查找路径.另外,我查看了Ruby Metaprogramming 2中的对象模型章节,在几个聊天室中询问,并制作了这个reddit线程.没学习C,我已经尽我所能来解决这个问题.
如上面的资源所述,在接收对象(如fido_instance)上进行方法查找时,会检查这6个位置(按顺序):
显然,该图是不完整的,并且所有这些单例类可能都不是在现实世界中创建的.尽管如此,这6个步骤还有很多不足之处,并未涉及以下情况.如果在单例类之上没有扩展/前置IClass fido_instance,那么就没有解释第4步是否在单例类上执行fido_instance.我不得不假设,因为整个方法查找会短路.
如果我猜测一组可以解释ruby的方法查找行为的步骤,它可能看起来像:
fido_instance.class方法.(显然,ruby不会使用自己的#class方法来进行方法查找,但它传达了进程的逻辑)fido_instance.class.superclass方法.继续添加.superclass并检查方法,直到没有剩余超类.(同样,ruby不会使用自己的#superclass方法)我还记得读过如果接收对象是一个类,有一个单独的方法查找过程,但我不记得在哪里.
那么什么是正确的,详细的解释,不涉及了解C?
在第二个参考文献中,有一个……宝石……我认为它触及了答案的核心:单例类的祖先。应用于您的对象,它将是:
fido_instance.singleton_class.ancestors
这将始终为您提供 Ruby 使用的方法查找顺序。当你这样看时,这很简单,这就是你问题的底线答案。Ruby 将从 singleton_class 开始,向上查找该方法的祖先。使用你的图表:
fido.singleton_class.ancestors
=> [Fetch, WagTail, DogClass, Object, Kernel, BasicObject]
Run Code Online (Sandbox Code Playgroud)
(注 1:Bark不是此输出的一部分,因为您使用的extend是include。稍后将详细介绍。)
(注2:如果一直到 都没有找到BasicObject,那么它将调用method_missing相同的祖先链。)
调用类上的方法时没有什么不同,因为在 Ruby 中,类只是 class 的一个实例Class。因此,就像以前一样,将继续搜索其祖先链DogClass.method1。method1DogClass.singleton_class
DogClass.singleton_class.ancestors
=> [Bark, Class, Module, Object, Kernel, BasicObject]
Run Code Online (Sandbox Code Playgroud)
既然您使用extend过Bark,我们就在这里找到它!因此,如果Bark定义了一个方法bark,那么您可以调用DogClass.bark,因为该方法是在DogClass“singleton_class”祖先中定义的。
要了解祖先树是什么(而不是每次都依赖打印出来),您只需要知道如何通过子类化、extend、include、prepend等来修改祖先。
include在类中添加模块C会将该模块添加到祖先链中,位于C其他所有模块之后和之前。prepend在类中添加模块C会将该模块添加到祖先链中的所有内容之前,包括C任何当前前置的模块。def x.method1添加method1到x.singleton_class. 类似地,x.extend(M)将添加到(但不是)M的祖先。请注意,后者正是 和 所发生的情况,但同样适用于任何对象。x.singleton_classx.classBarkDogClass.singleton_class从上面的列表中删除是extend因为它不会修改对象的祖先链。它确实修改了该对象的祖先singleton_class——正如我们所见,Bark包含在DogClass.singleton_class.ancestors.
切线:
上面关于类方法的内容是我理解单例类对于 Ruby 的重要性的关键。你显然不能定义barkon DogClass.class,因为DogClass.class == Class我们不想要barkon Class!那么我们如何才能允许DogClass成为 的实例Class,从而允许它具有bark为DogClass但不相关的类定义的(类)方法呢?使用单例类!通过这种方式,定义一个“类方法”,就像在def self.xclass 内部一样C,有点像C.singleton_class.send(:define_method, :x) {...}.
| 归档时间: |
|
| 查看次数: |
194 次 |
| 最近记录: |