Ruby on rails 如果类本身就足够了,为什么要使用include模块
在下面的代码中,使用了include模块。在我看来,如果删除了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 Module.new{
class_eval我猜,但是……他们不想覆盖“destroy”方法,而是想让它被某个最终用户(您或我)重载,而不删除这个“reflection.clear”功能
因此,通过将其作为一个模块,他们可以调用“super”,这将调用原始销毁或重载版本(由最终用户编写).由于包含
,销毁
方法不会被覆盖。它落在实际类派生的ghost类中。这样,当调用AR对象上的销毁
时,将调用原始类,超级
将从匿名模块调用一个(稍后将从其派生的类调用originaldestroy
)
确实有点棘手。首先让我们弄清楚一件事。当他们在类中调用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"