gpt4 book ai didi

ruby-on-rails - 为什么在 class_eval 本身就足够时使用 include 模块

转载 作者:数据小太阳 更新时间:2023-10-29 06:58:04 24 4
gpt4 key购买 nike

在下面的代码中使用了 include 模块。如果删除包含模块,那么我看到它的方式也会创建一个实例方法。那为什么用户包含模块?

http://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations.rb#L1416

  include Module.new {
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def destroy # def destroy
super # super
#{reflection.name}.clear # posts.clear
end # end
RUBY
}

最佳答案

首先让我们弄清楚一件事。当他们在 class_eval 中调用 super 时——这与他们使用 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>

这是有道理的,因为第一个 foo 没有在某个父类(super class)中定义,也没有在查找链上的任何地方定义(这是 super 指向的地方)。但是,您可以定义第一个 foo,这样当您稍后覆盖它时 — 它可以通过调用 super 获得。这正是他们希望通过模块包含实现的目标。

class Foo
include Module.new { class_eval "def foo; 'foo' end" }

def foo
super + 'bar'
end
end

Foo.new.foo # => "foobar"

这是可行的,因为当您包含一个模块时,ruby 会将它插入到查找链中。这样您就可以随后在第二个方法中调用 super,并期望调用包含的方法。伟大的。

但是,您可能想知道,为什么不简单地包含一个没有所有技巧的模块呢?他们为什么使用 block 语法?我们知道我上面的例子完全等价于下面的例子:

module A
def foo
'foo'
end
end

class Foo
include A

def foo
super + 'bar'
end
end

Foo.new.foo # => "foobar"

那么他们为什么不这样做呢?答案是——调用反射。他们需要捕获当前上下文中可用的变量(或方法),即反射

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

只是为了说明。

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 的类的子类。

我希望这已经清楚了。

关于ruby-on-rails - 为什么在 class_eval 本身就足够时使用 include 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3444607/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com