问题 在ruby上,为什么包括私有和扩展是公共的?


在红宝石上,原因是什么 include 是私人的,而 Object#extend 是公开的?


6915
2017-11-18 10:34


起源

谢谢您的回答! - Vlad Zloteanu


答案:


Object#extend  具有 公开,否则你将无法使用它。毕竟,它的目的是将一个模块混合到一个对象中,所以你通常称它为 obj.extend(Foo),这是私人方法无法实现的。

Module#include 通常只在模块体内使用,如下所示:

class Bar
  include Foo
end

即它通常在没有接收器的情况下被调用,因此它不必是公开的。当然,它没有  是私人的。

我猜测它是私有的原因是它更具侵入性,因为它改变了它的行为 一切 的例子 Bar,而 Object#extend 只更改单个对象。因此, Module#include 从某种意义上说,它“更危险”,因此被私有化。

我不知道这是否是实际原因,但它与其他类似方法一致 Module#define_method


10
2017-11-18 13:11



它没有 有 成为。如果它是私有的,你可以使用它: obj.send(:extend, Foo), obj.instance_eval{ extend Foo },不包括模块的情况 class Bar; extend Foo; end - Marc-André Lafortune
@ Marc-AndréLafortune:或者 class << obj; extend Foo; end, 当然。就像我说的那样,这只是猜测。 - Jörg W Mittag
我回复你的第一句话“Object#extend 必须公开,否则你将无法使用它。“ - Marc-André Lafortune
PS:我想不出一个人会怎么做的情况 class << obj; extend Foo; end,如在你的评论中。 - Marc-André Lafortune
快进到2014年。 Module#include (和 Module#prepend)在v2.1中公开。 - Cary Swoveland


能够跑 Foo.include(Bar) 在任何时候都很可能是非常讨厌的错误的来源。


1
2017-11-18 14:48





为了补充JörgWMittag的答案,Object#extend还可以用于包含要在类级别使用的模块实例方法(也可用于该类的所有实例):

module Foo
  def bar (baz)
  end
end

class Qux
  extend Foo

  bar 'asdf'
end

1
2017-12-01 21:29