简体   繁体   中英

Extending an object multiple times with the same module in Ruby

Given a class Klass and an instance k of this class:

class Klass
  def hello
    'Hello'
  end
end

k = Klass.new
k.hello        #=> "Hello"

I can extend this instance with a module to add methods to this specific instance without altering the whole class (ie all instances):

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

k.extend(Mod)
k.hello        #=> "Hello, World!"

But what happens if I extend k multiple times with the same module?

k.extend(Mod)
k.extend(Mod)
k.extend(Mod)
k.hello        #=> "Hello, World!"

Are the subsequent calls ignored or is the object extended multiple times?

To put it another way: is it "safe" to extend an object multiple times?

I think the subsequent calls are ignored (unless you have something deeper in mind). The following result shows Mod only once in the ancestor list.

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]

sawa already answered the actual question, but this could be relevant, too. Although the Mod is added only once to the object's (singleton class') ancestors, the extended callback is called every time:

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>"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM