Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby module prepend vs derivation

Tags:

ruby

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?

like image 817
muichkine Avatar asked Jul 23 '14 10:07

muichkine


2 Answers

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
like image 139
Jörg W Mittag Avatar answered Nov 17 '22 03:11

Jörg W Mittag


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.

like image 31
Windor C Avatar answered Nov 17 '22 05:11

Windor C