使用Ruby中的相同模块多次扩展对象

Ste*_*fan 0 ruby

给定一个类Klassk这个类的实例:

class Klass
  def hello
    'Hello'
  end
end

k = Klass.new
k.hello        #=> "Hello"
Run Code Online (Sandbox Code Playgroud)

我可以extend使用模块将此实例添加到此特定实例,而无需更改整个类(即所有实例):

module Mod
  def hello
    "#{super}, World!"
  end
end

k.extend(Mod)
k.hello        #=> "Hello, World!"
Run Code Online (Sandbox Code Playgroud)

但是如果我k使用相同的模块多次扩展会发生什么?

k.extend(Mod)
k.extend(Mod)
k.extend(Mod)
k.hello        #=> "Hello, World!"
Run Code Online (Sandbox Code Playgroud)

是后续调用被忽略还是对象被多次扩展?

换句话说:多次扩展对象是否"安全"?

saw*_*awa 5

我认为后续的调用会被忽略(除非你有更深入的思考).以下结果Mod仅在祖先列表中显示一次.

class Klass; end
module Mod; end
k = Klass.new
k.extend(Mod)
k.extend(Mod)
k.extend(Mod)
k.singleton_class.ancestors
# => [#<Class:#<Klass:0x007f7787ef7558>>, Mod, Klass, Object, Kernel, BasicObject]
Run Code Online (Sandbox Code Playgroud)


Ste*_*fan 5

sawa 已经回答了实际问题,但这也可能是相关的.虽然Mod只对对象的(单例类)祖先添加一次,但extended每次都会调用回调:

class Klass
end

module Mod
  def self.extended(mod)
    puts "#{self} extended in #{mod}"
  end
end

k = Klass.new
k.extend(Mod)
#=> "Mod extended in #<Klass:0x007fabbb029450>"
k.extend(Mod)
#=> "Mod extended in #<Klass:0x007fabbb029450>"
k.extend(Mod)
#=> "Mod extended in #<Klass:0x007fabbb029450>"
Run Code Online (Sandbox Code Playgroud)