惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
CXSECURITY Database RSS Feed - CXSecurity.com
GbyAI
GbyAI
aimingoo的专栏
aimingoo的专栏
Recent Announcements
Recent Announcements
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
A
About on SuperTechFans
G
Google Developers Blog
MyScale Blog
MyScale Blog
N
Netflix TechBlog - Medium
博客园 - 叶小钗
Know Your Adversary
Know Your Adversary
V
Vulnerabilities – Threatpost
D
DataBreaches.Net
P
Palo Alto Networks Blog
C
Cisco Blogs
H
Hackread – Cybersecurity News, Data Breaches, AI and More
NISL@THU
NISL@THU
Forbes - Security
Forbes - Security
Microsoft Security Blog
Microsoft Security Blog
T
The Exploit Database - CXSecurity.com
阮一峰的网络日志
阮一峰的网络日志
腾讯CDC
Schneier on Security
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
N
News and Events Feed by Topic
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Engineering at Meta
Engineering at Meta
Last Week in AI
Last Week in AI
AWS News Blog
AWS News Blog
Security Latest
Security Latest
H
Heimdal Security Blog
小众软件
小众软件
Cyberwarzone
Cyberwarzone
The Hacker News
The Hacker News
P
Privacy International News Feed
Stack Overflow Blog
Stack Overflow Blog
The Cloudflare Blog
Scott Helme
Scott Helme
博客园 - 【当耐特】
Latest news
Latest news
Microsoft Azure Blog
Microsoft Azure Blog
Y
Y Combinator Blog
Jina AI
Jina AI
Spread Privacy
Spread Privacy
量子位
博客园_首页
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Blog — PlanetScale
Blog — PlanetScale
雷峰网
雷峰网

Ruby

一個用 DIDComm 實現服務器間通信的 Rails demo - V2EX RubyConf China 2024 参会报告 - Day 1 - V2EX 有对 Ruby 感兴趣的吗? - V2EX MRuby Devkit 一个简单的脚手架,帮助你像 Go 一样把 Ruby 编译成可执行二进制文件 - V2EX 使用 Ruby-build 在 MacOS 上 编译 Portable Ruby - V2EX [翻译] Async Ruby(异步 Ruby) - V2EX [翻译] Ruby Fiber Scheduler - V2EX Ruby 3.2.0 发布 - V2EX Ruby on Mac - V2EX 用 100 行 Ruby 代码模拟 JavaScript 的 Eventloop - V2EX 管窥蠡测从思考游戏到实现 2048 - V2EX 用 Ruby 讲从创业到 996 公司的故事(戏说 master-worker 模式) - V2EX Sinatra 源码分析 (一):set 系统工作原理 - V2EX 《Ruby 设计模式》笔记 - V2EX Ruby 标准库有趣部分摘要 - V2EX 并行并发进程线程协程 GIL 概念简明解释笔记(Ruby 举例) - V2EX Sinatra 的 app 模板,提供一些胶水代码支持类似 Rails 的体验 - V2EX 有在深圳至简天成的吗? 求加微信 - V2EX Ruby 3.0.0 Released - V2EX 新建了个 ruby 中文讨论群 - V2EX Language Hopping, Ruby 为什么不火,一点瞎想 - V2EX ruby,一代优秀语言就这样陨落了吗? - V2EX ruby 的 "a" 和 :a 能转换吗 - V2EX 求大佬帮安装一个 mastodon,有偿! - V2EX notepad++ ssh 一些个小坑 - V2EX 有什么好的方法/IDE 阅读 Gem 库的源码? - V2EX 问一个 ruby 的问题 - V2EX 用 discourse 搭了个论坛 求测试 - V2EX 找小伙伴一起开发和完善一个 Ruby 增量代码覆盖率统计工具 - V2EX 都在说抑郁,我们学一下 ruby 吧,一门让你快乐的语言 - V2EX ruby2.6 的 jit 大家感觉怎么样? - V2EX 在 one-liner 文本处理方面, ruby 比 perl 要逊色吗? - V2EX 使用 ruby 写了一个周报系统 - V2EX ruby 的 devkit 安装 - V2EX 总听人说 ruby 代码写起来很爽,有多爽?怎么个爽法? - V2EX RubyGems 注册不了的? - V2EX Ruby 破环方法为什么比非破坏方法慢一些? - V2EX Ruby Conference 2017 AU - V2EX ruby 这么优雅的语言,怎么没有像 python 这样流行开来? - V2EX Ruby 中 Singleton 方法的另一种理解方式 - V2EX 需要学习 ruby,想问现在 ruby 的主流版本是多少? - V2EX Ruby 的内存占用极限? Ruby 写了一个命令行火车票查看器 - V2EX 有谁用过 Ruby 写的比特币交易平台 Peatio,admin 面板进不去,求教啊啊啊啊啊啊啊 - V2EX 和隔壁的 python 比起来,这节点好冷清 阿里云 OSS Ruby SDK 开发手记 - V2EX 淘宝 RubyGems 镜像有段时间没同步了 - V2EX 为什么 Ruby 给人一种「只有 Rails」的印象?
Ruby 的方法查找再往前一步 - V2EX
Mark24 · 2021-07-29 · via Ruby

有更好的方法可以告诉我,我最新在学习 Ruby

最新的修改会更新在 BLOG

我的博客

RubyChina 讨论帖


背景

《 Ruby 元编程(第二版)》 5.4 节 单件类 在 Page125 这页,讲了一种情况:


class C
  def a_method
    'C#a_method()'
  end
end



class C
  class << self
    def a_class_method
      '#C.a_class_method() #singleton'
    end
  end
end

class D < C;end

obj = D.new


D.a_class_method # => '#C.a_class_method() #singleton'

D.a_class_method 他是如何查找的呢?

本文就是寻找这个的答案。讲的是 Ruby 的方法查找再往前走一步。

为了说明这个问题,先要啰嗦的做一些铺垫。

下文中,此书简称为《元编程》

这张图实在总结的太美丽了。先放在这里。图片的出处,可以参考文末。

二、Ruby 一般方法查找规则

《元编程》里面里面总结了 Ruby 的查找规则:

“向右一步,然后向上查找”。

意思就是,向右寻找他的父,然后开始往上寻找继承关系,通过这种方式查找方法。

比如以下代码

class C
  def a_method
    'C#a_method()'
  end
end


class D < C;end

obj = D.new
obj.a_method

obj 如何查找 a_method 方法呢?

如果我们给 obj 对象添加单例类,他会如何查找呢?


class C
  def a_method
    'C#a_method()'
  end
end


class D < C;end

obj = D.new

# 定义单例类

class << obj
  def a_singleton_method
    "obj#a_singleton_method"
  end
end

obj.a_singleton_method 

obj.a_singleton_method 会如何查找方法呢?

可以通过一下方式检验


obj.singleton_class.superclass # => D

他会按照如图的方式,其实实例对象创造了一个 单例类 可以标记为 #obj,用#表示单例类。 #obj 会出现在对象和真正的类中间。

我们也能用上面

“向右一步,然后向上查找”。

来指导我们查找,只不过对象存在一个单例类罢了。

三、新的问题出现

但是问题来了,回到文章的最开头。


class C
  def a_method
    'C#a_method()'
  end
end



class C
  class << self
    def a_class_method
      '#C.a_class_method() #singleton'
    end
  end
end

class D < C;end

obj = D.new


D.a_class_method # => '#C.a_class_method() #singleton'

这个例子。在类 C 上定义了单例方法,并且我们指导所有东西在 Ruby 里都是对象,都可以定义单例方法。

这就是文章开头最先的图片。所有的类都可以定义单例类。这种情况下,D.a_class_method 应该如何查找呢?

“向右一步,然后向上查找”。

似乎帮不了我们了。因为我们面临一个问题,让我来描述下:

我们把 D 当做一个对象,开始寻找他的方法。

拿这幅图做例子:

Dog 开始寻找定义的方法,向右一步,进入自己的 单例类 #Dog,然后应该做什么,选择向上么?是走 他的父类 Class,还是 应该往 单例类的继承链往上找呢?

《元编程》文末的几句话,似乎在暗示黄色这条线的寻找方向,但是作者并没有真正说清楚:

三、寻找答案

我先放出答案,如下图所示:

对象的方法,遵循

“向右一步,然后向上查找”。

类方法的查找是我们关心的,可以看到实际结果是,它沿着继承的单例类一路向上,然后再进入父类。

寻找这个答案的过程中,我看了挺多资料和文字,还有问一些 Ruby 方面的朋友都没有真正分析到这一步。

我最后是怎么找到答案的呢? 这就得借助 Ruby 自身完善的自省机制。(吐槽,其他语言可能都没有实现的那么细致)。

其实 Ruby 自身的很多属性都绑定在自身了,直接向 Ruby 问答案就好了


class C
  def a_method
    'C#a_method()'
  end
end



class C
  class << self
    def a_class_method
      '#C.a_class_method() #singleton'
    end
  end
end

class D < C;end

obj = D.new


D.a_class_method # => '#C.a_class_method() #singleton'

我们知道 obj.ancestors 可以打印继承关系,但是这个很遗憾的是它不会打印 单例类。

单例类实际上是一个隐藏的存在。这也就是研究这个问题很难得地方,因为隐藏,似乎只能通过源码和外部资料去查看。

实际上我们是可以拿到 obj.singleton_class 的,然后我们前面分析了一些结论,大致给出了一个对象的继承模型。

obj.singleton_class.ancestors

# => [#<Class:#<D:0x00007feae092efc8>>, D, C, Object, Kernel, BasicObject]

就可以打印出,对象查找的顺序。

同理,我们想要知道 D 的方法的查找顺序

D.singleton_class.ancestors

# => [#<Class:D>, #<Class:C>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject]

这个其实就是 D 查找方法的顺序,可以看到,他先是把所有的单例类走了一遍,然后开始进入自己的父。

四、总结

最后,这句话

“向右一步,然后向上查找”。

有了新内涵, 向右一步的过程中,优先的走单例类(如果有的话)以及单例的继承,结束后,开始进入自己真正的父,即向上在继承关系中寻找。

单例类也可以看成是一种外挂方法(比喻不严谨但是很好理解),先在外挂方法里找,也可以顺着外挂继承链找。找不到再到继承关系里面找。

题外话

有人可能会问,为啥继承体系要搞得那么复杂?

借用 《元编程》里面的一句

这样你就可以在 D 中 调用 C 的方法了。

把对象穿成链表,然后相当于你可以拥有和复用这个链条上所有的方法。

元编程的一部分思想也就是动态的修改、创造、转发方法。还有 《元编程》里面提到的 “自由方法”我的理解就像是把继承链中某些方法复制,然后粘贴到当前对象执行,在继承链上跳跃执行方法……

这一切都是为了极大地自由。

我以前一致不太理解“Ruby 是快乐优先”这句话是什么意思,现在我的理解——这种快乐就是自由,拥有自由的快乐。

其他

图片来自文章

安利一波作者图片配色

参考

书籍推荐 《 Ruby 元编程(第 2 版)》

BLOG

有更好的方法可以告诉我,我最新在学习 Ruby

最新的修改会更新在 BLOG

我的博客

RubyChina 讨论帖