如何调用父模块构造函数?

时间:2013-12-30 08:21:10

标签: ruby module mixins

我想调用我在一个类中包含的两个模块的构造函数,但我不知道该怎么做。

module GameObject
  attr_reader :x, :y
  def initialize(x, y)
    @x, @y = x, y
  end
end

module Attackable
 attr_reader :health, :damage
 def initialize(health, damage)
   @health, @damage = health, damage
 end
end

class SuperMario
  include GameObject
  include Attackable
  def initialize(x, y, health, damage)
    .. how to call the above constructors?
  end
end

如何调用Attackable和GameObject的构造函数?

3 个答案:

答案 0 :(得分:1)

您可以在类初始化程序中显式调用module的方法,如下所示:

def initialize(x, y, health, damage)
   m = GameObject.instance_method( :initialize )
   m.bind(self).call( x, y )
   m = Attackable.instance_method( :initialize )
   m.bind(self).call( health, damage)
end

答案 1 :(得分:0)

我想你来自C ++世界,允许多重继承...简而言之,Ruby只提供单一继承,并且不允许挑选你正在调用的父方法。温和地说,这就是你想要实现的目标。模块不会为您提供任何良好的解决方法 - 即使在考虑prependself.included以及元编程工具箱的其余部分之后 - 除了在没有名称冲突的特定情况下

可以做的是重命名initialize方法,使其逻辑在特定于其模块的函数中,并调用 。除此之外:在模块中定义initialize方法通常会产生代码气味。

答案 2 :(得分:0)

我今天学到了新东西:

module B
  def cat(a) puts "in B, a = #{a}" end
end

module C
  def cat(a) puts "in C, a = #{a}"; super a+1; end
end

class A
  include B
  include C
  def cat(a) puts "in A, a = #{a}"; super a+1; end
end

A.new.cat(2)
# => in A, a = 2
# => in C, a = 3
# => in B, a = 4

您的问题不仅限于initialize,这就是我用通用方法说明此行为的原因。我原以为includes会混合使用其他两个cat方法,因此结果与:

相同
class D
  def cat(a) puts "in 1st, a = #{a}" end
  def cat(a) puts "in 2nd, a = #{a}"; super a+1; end
  def cat(a) puts "in 3rd, a = #{a}"; super a+1; end
end

D.new.cat(2)
# => in 3rd, a = 2
# => module.rb:24:in `cat': super: no superclass method `cat' for
#    #<D:0x007faadb99acb8> (NoMethodError) from module.rb:27:in `<main>'

我对@ sawa关于“超级”的评论感到困惑,发现我错了。 (我希望不是所有读这篇文章的人都会思考,“那么还有什么新东西?”。)