Ruby module prepend vs derivation

2020-07-11 06:46发布

问题:

What are the differences between:

module Mod   
   def here
     puts 'child'
   end    
end

class A
  prepend Mod
  def here
    puts 'parent'
  end
end

and

class A
   def here
     puts 'parent'
   end
end

class B < A
  def here
    puts 'child'
  end
end

Or another way to put it: is derivating a class the same as prepending a module of the child's code?

回答1:

No, it is not. B can only inherit from one class, but Mod can be prepended to many classes. If you were to call super inside B#here, it would always refer to A#here, but inside of Mod#here, it will refer to the #here instance method of whatever class Mod was prepended to:

module Mod   
  def here
    super + ' Mod'
  end    
end

class A
  prepend Mod
  def here
    'A'
  end
end

class B
  prepend Mod
  def here
    'B'
  end
end

A.new.here
# => 'A Mod'

B.new.here
# => 'B Mod'

and

class A
  def here
    'A'
  end
end

class B
  def here
    'B'
  end
end

class C < A
  def here
    super + ' C'
  end
end

C.new.here
# => 'A C'

class C < B
  def here
    super + ' C'
  end
end
# TypeError: superclass mismatch for class C


回答2:

No, it's totally different.

One can prepend as many modules as he wants.

module A
  def foo; "A" end
end

module B
  def foo; "B" end
end

class C
  prepend A, B   # Prepending is done by this line

  def foo; "C" end
end
### take a look at it!
C.ancestors # => [A, B, C, Object, Kernel, BasicObject]
C.new.foo # => "A"

Ruby implements prepend and inheritance using different ways. prepend is internally achieved by including modules, which causes the surprising ancestors.

here is another question about prepend which may be helpful.



标签: ruby