【问题标题】:Why does Ruby module inclusion exclude the module's singleton class?为什么 Ruby 模块包含排除模块的单例类?
【发布时间】:2011-04-20 09:33:43
【问题描述】:

当类在 Ruby 中被继承时,单例类也被继承:

class A
  def self.hello
    puts "hello"
  end
end

class B < A
end

B.hello #=> "hello"

但对于模块,情况并非如此:

module M
  def self.goodbye
    puts "goodbye"
  end
end

class A
  include M
end

A.goodbye #=> NameError

为了绕过这个限制,许多人使用了这个丑陋的黑客:

module M
  def self.included(c)
    c.extend ClassMethods
  end

  module ClassMethods
    def goodbye
      puts "goodbye"
    end
  end
end

好的,所以我的问题是:这种模块限制背后是否存在理论/概念上的原因?还是只是实施困难?

查看 C 源代码 (YARV/MRI) 后,我可以确定存在一个实现困难(不是无法克服,但都是一样的),但这是唯一的原因吗?这种限制还有其他原因吗?

谢谢

【问题讨论】:

  • 他们为什么要这样做?包含模块与继承类不同。
  • @Mladen,我不买这个。如果概念上的区别如此清晰,那么为什么人们(甚至是非常顶级的 Ruby 程序员)试图通过使用ClassMethods hack 来绕过这个限制?进一步——为什么模块的性质以某种方式暗示了这个特定的限制。
  • 恕我直言,模块混合!= 多重继承,所以无论某些人可能在做什么并不能真正证明什么。顺便说一句,您能否通过一个真实的示例来说明对 hack 的需求,例如,通过包含模块 A 并通过模块 B 扩展来实现相同的功能是无法实现的?
  • @Mladen,你的例子正是黑客派上用场的地方......你不再需要include Aextend B,因为包括A就足够了.同样,简单地说“它们不同”而不给出任何解释也很弱。我的问题是这种差异背后的理论是什么......或者根本没有理论,这只是一个实施困难?查看源代码,我相信这只是一个实施困难。
  • 请注意,我并不是说您的期望是错误的。简单地说,include 在文档中被明确定义为除了在模块上调用append_features 之外什么都没有,这反过来意味着添加模块的常量、方法和模块变量。它不代表继承。

标签: ruby inheritance module singleton mixins


【解决方案1】:

除非任何人都能提出令人信服的论点,否则我认为限制仅在于实施难度。尽管如此,过去几天我一直在解决这个问题,并且(在测试版中)一个名为 include_complete 的新版本包含解决了这些困难并允许模块继承像类继承一样工作(引入单例)

在此处查看项目:http://github.com/banister/include_complete

请注意,该项目仍处于测试阶段,但到目前为止似乎仍能按预期工作

【讨论】:

    【解决方案2】:

    警告:以下只是推测。

    如果您使用类,则需要单例类方法,因为您依赖它们来创建对象(例如MyClass.new)。如果您使用的是模块,则不需要它们,因为您不能纯粹从模块中创建对象。

    【讨论】:

    • 单例方法的用途远不止创建对象;我不认为这可能是原因,但谢谢:)
    猜你喜欢
    • 1970-01-01
    • 2016-02-24
    • 2015-02-10
    • 2011-06-10
    • 2013-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-01
    相关资源
    最近更新 更多