【问题标题】:Ruby module prepend vs derivationRuby 模块前置与派生
【发布时间】:2014-07-23 10:48:42
【问题描述】:

两者有什么区别:

module Mod   
   def here
     puts 'child'
   end    
end

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

class A
   def here
     puts 'parent'
   end
end

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

或者换一种说法:派生类是否等同于添加子代码的模块?

【问题讨论】:

  • def do 不是一个有效的语法.. 你应该给它一个名字.. do 是一个关键字,你不能给它一个方法名..
  • @ArupRakshit do 是一个有效的方法名称。
  • @sawa 我不知道...这不是缩进...为什么要尝试将方法名称命名为do..无论如何。它的其他代码。我不会给它起一个像do 这样的名字,因为do 进入了 block 语法。
  • 我将方法名称更改为here 以澄清问题的含义。

标签: ruby


【解决方案1】:

不,不是。 B 只能从一个类继承,但Mod 可以附加到多个类。如果您要在B#here 中调用super,它将始终引用A#here,但在Mod#here 内部,它将引用#here 的任何类的实例方法Mod 被添加到:

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'

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

【讨论】:

  • 那是因为你定义了两次 C 类。您的第二个示例不使用前置模块。 :)
  • @muichkine:是的,完全正确。您询问了预置 mixin 和继承类之间的区别,这是区别之一:您可以预置多个 mixin,但只能继承一个类。
【解决方案2】:

不,完全不同。

可以根据需要添加任意数量的模块。

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 使用不同的方式实现prepend 和继承。 prepend 是通过包含模块在内部实现的,这导致了令人惊讶的ancestors

here 是关于prepend 的另一个问题,可能会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-18
    • 1970-01-01
    • 2012-07-17
    • 1970-01-01
    • 2018-03-12
    相关资源
    最近更新 更多