【问题标题】:Why does the Ruby module Kernel exist?为什么 Ruby 模块 Kernel 存在?
【发布时间】:2016-11-12 09:05:41
【问题描述】:

Ruby 中的OO 设计 一书中,Sandi Metz 说模块的主要用途是用它们实现鸭子类型并将它们包含在所需的每个类中。为什么 Ruby KernelObject 中包含的一个模块?据我所知,它没有在其他任何地方使用。使用模块有什么意义?

【问题讨论】:

  • 我认为你是对的,它可能不会被认为是理想的 OO 设计,并且寻找理由来证明它的合理性可能是错误的。
  • 你是对的,它几乎是反OO的。 Kernel 包含所有那些为了方便而存在并忽略其接收者的“程序”(即不要对 self 做任何事情)。

标签: ruby oop


【解决方案1】:

理想情况下,

  • 精神上的方法(适用于任何对象),即使用接收者的方法,应该在Object类上定义,而
  • Procedures(全局提供),即忽略接收者的方法,应该收集在Kernel模块中。

Kernel#puts,例如不对其接收者做任何事情;它不调用私有方法,不访问它的任何实例变量,它只作用于它的参数。

Ruby 中的过程是通过使用 Ruby 的特性来伪造的,即可以省略等于 self 的接收器。它们也经常被设为私有,以防止它们被显式接收器调用,从而更加混乱。例如,"Hello".puts 将打印一个换行符,因为puts 只关心它的参数,而不关心它的接收者。通过将其设为私有,它只能被称为puts "Hello"

实际上,由于 Ruby 的悠久历史,这种分离并不总是被严格遵循。一些Kernel 方法记录在Object 中,反之亦然,而且当您定义一些看起来 像全局过程的东西时,这也更加复杂,并且根据上述推理,它最终应该在Kernel 中结束,它实际上以Object 中的私有实例方法结束。

【讨论】:

    【解决方案2】:

    正如您已经指出的:模块提供了一种收集和构造行为的方法,内核模块也是如此。这个模块很早就被混入到 Object 类中,所以每个 Ruby 类都会提供这些方法。在层次结构之前只有一个 BasicObject,它的子对象的目的只是为了通过内核方法进行扩展。 BasicObject 只有 7 个非常基本的方法,例如 new__send____id__

    class Object < BasicObject
      include Kernel # all those many default methods we appreciate :)
    end
    

    【讨论】:

      猜你喜欢
      • 2019-12-05
      • 1970-01-01
      • 1970-01-01
      • 2018-07-09
      • 1970-01-01
      • 2019-06-01
      • 2011-04-20
      • 1970-01-01
      • 2011-09-23
      相关资源
      最近更新 更多