Ruby on rails 如果类本身就足够了,为什么要使用include模块

Ruby on rails 如果类本身就足够了,为什么要使用include模块,ruby-on-rails,ruby,Ruby On Rails,Ruby,在下面的代码中,使用了include模块。在我看来,如果删除了include模块,那么还会创建一个实例方法。那么用户为什么包括模块呢 include Module.new{ class_eval我猜,但是……他们不想覆盖“destroy”方法,而是想让它被某个最终用户(您或我)重载,而不删除这个“reflection.clear”功能 因此,通过将其作为一个模块,他们可以调用“super”,这将调用原始销毁或重载版本(由最终用户编写).由于包含,销毁方法不会被覆盖。它落在实际类派生的ghost

在下面的代码中,使用了include模块。在我看来,如果删除了include模块,那么还会创建一个实例方法。那么用户为什么包括模块呢

include Module.new{

class_eval我猜,但是……他们不想覆盖“destroy”方法,而是想让它被某个最终用户(您或我)重载,而不删除这个“reflection.clear”功能


因此,通过将其作为一个模块,他们可以调用“super”,这将调用原始销毁或重载版本(由最终用户编写).

由于
包含
销毁
方法不会被覆盖。它落在实际类派生的ghost类中。这样,当调用AR对象上的
销毁
时,将调用原始类,
超级
将从匿名模块调用一个(稍后将从其派生的类调用original
destroy


确实有点棘手。

首先让我们弄清楚一件事。当他们在
类中调用
super
时,eval
-这与他们为什么使用
include Module.new{}完全无关
事情。事实上,在
destroy
方法中调用的
super
与回答您的问题完全无关。destroy方法中可能存在任意代码

现在我们已经把事情解决了,下面是发生的事情

在ruby中,如果您只是定义一个类方法,然后在同一个类中再次定义它,您将无法调用
super
来访问前面的方法

例如:

class Foo
  def foo
    'foo'
  end

  def foo
    super + 'bar'
  end
end

Foo.new.foo # => NoMethodError: super: no superclass method `foo' for #<Foo:0x101358098>
这是可行的,因为当您包含一个模块时,ruby会将其插入到查找链中。这样您就可以在第二个方法中调用
super
,并期望调用包含的方法。太好了

但是,您可能会想,为什么不简单地包含一个没有所有技巧的模块?为什么它们使用块语法?我们知道我上面的示例与下面的示例完全相同:

module A
  def foo
    'foo'
  end
end

class Foo
  include A

  def foo
    super + 'bar'
  end
end

Foo.new.foo # => "foobar"
那么他们为什么不这样做呢?答案是-调用
reflection
。他们需要捕获当前上下文中可用的变量(或方法),即
reflection

因为他们使用块语法定义新模块,所以块外的所有变量都可以在块内使用。方便

只是为了说明一下

class Foo
  def self.add_foo_to_lookup_chain_which_returns(something)
    # notice how I can use variable something in the class_eval string
    include Module.new { class_eval "def foo; '#{something}' end" }
  end
end

# so somewhere else I can do

class Foo
  add_foo_to_lookup_chain_which_returns("hello")

  def foo
    super + " world"
  end
end

Foo.new.foo # => "hello world"
整洁,嗯

现在让我再次强调一下。在您的示例中,
destroy
方法内部对
super
的调用与上述任何一种方法都无关。他们调用它是出于自己的原因,因为可能发生这种情况的类正在子类化另一个已经定义了
destroy
的类


我希望这能说明问题。

也许是ping rails核心人员?
module A
  def foo
    'foo'
  end
end

class Foo
  include A

  def foo
    super + 'bar'
  end
end

Foo.new.foo # => "foobar"
class Foo
  def self.add_foo_to_lookup_chain_which_returns(something)
    # notice how I can use variable something in the class_eval string
    include Module.new { class_eval "def foo; '#{something}' end" }
  end
end

# so somewhere else I can do

class Foo
  add_foo_to_lookup_chain_which_returns("hello")

  def foo
    super + " world"
  end
end

Foo.new.foo # => "hello world"