7

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?

muichkine
  • 2,890
  • 2
  • 26
  • 36
  • `def do` is not a valid syntax.. You should give it a name.. `do` is a keyword, you can't give it a method name.. – Arup Rakshit Jul 23 '14 at 11:10
  • 2
    @ArupRakshit `do` is a valid method name. – sawa Jul 23 '14 at 11:11
  • @sawa I don't know... It is not indenting.. Why should one try to give a method name as `do`.. Anyway. Its other's code. I wouldn't give it a name like `do` as, `do` comes into the *block* syntax. – Arup Rakshit Jul 23 '14 at 11:13
  • 1
    I changed the method name to `here` to clarify what the question is about. – muichkine Jul 23 '14 at 11:16

2 Answers2

4

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
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • Thats because you define C class twice. Your second example uses no prepend module. :) – muichkine Jul 29 '14 at 08:10
  • @muichkine: Yes, exactly. You asked about the difference between prepending a mixin and inheriting a class, and that's one of the differences: you can prepend multiple mixins, but only inherit one class. – Jörg W Mittag Jul 29 '14 at 10:06
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.

Community
  • 1
  • 1
Windor C
  • 1,120
  • 8
  • 17