在Ruby中,是否可以将模块移到祖先链上?

时间:2016-04-22 16:52:21

标签: ruby

我有一个Ruby类C,其中包含一些第三方模块,比如AB

模块A通过C的类继承链间接包含在内;假设我无法控制A被包含的位置。现在,C直接包含B,但B包含另一个模块D,它恰好提供A提供的功能,如下所示:

class C < Base

  # Base includes A

  include B   # includes D

  # methods in A overridden by D

end      

祖先链是这样的(其中...表示与此讨论无关的零个或多个其他祖先):

C ... B ... D ... A 

我希望A的功能优先于D:我想移动A,因此它位于祖先链中的D前面,就像这样:

C ... A ... B ... D

我尝试过再次包含A,但这不起作用。有没有办法做到这一点?

3 个答案:

答案 0 :(得分:2)

一旦建立,就无法改变mixin层次结构。只有包含顺序决定了层次结构。在将Ti.Media.saveToPhotoGallery(webView.toImage()); 加入A之后,您必须C加入B(第一次),或者,如果您将C添加到A如果C包含在D之后,它将优先于B

答案 1 :(得分:1)

当然可以。我每天都会这样做,周日也会两次。好吧,有点......

.   # Match "any" character
*   # Do the previous thing (.) zero OR MORE times (any number of times)
\   # Escape the next character - treat it as a plain old character
.   # Escaped, just means "a dot".

正如所料:

module A
  def hiya(str)
    puts "ho #{str}"
  end
  def if_what?
  end
end

module D
  def hiya(str)
    puts "hi #{str}"
  end
  def what_if?
  end
end

module B
  include D
end

class C
  include A
  include B
end

要调用C.ancestors #=> [C, B, D, A, Object, Kernel, BasicObject] a = C.new #=> #<C:0x007fc56324ed40> a.hiya("Lois") hi Lois 的实例方法而不是A,我们可以写:

D

让我们看看:

(A.instance_methods & D.instance_methods).each { |m| D.send(:remove_method, m) }

答案 2 :(得分:1)

您几乎可以做到这一点。您不能将一个类/模块移到层次结构中,但是可以克隆一个模块,然后将该匿名模块克隆插入到其他祖先的前面。检查一下:

module A
  def salutations
    "a"
  end
end

module D
  def salutations
    "d"
  end
end

module B
  include D
end

class Base
  include A
end

class C < Base
  include B
end

c = C.new
puts c.salutations

#=> d

到目前为止,很好。

现在:

module A
  def salutations
    "a"
  end
end

module D
  def salutations
    "d"
  end
end

module B
  include D
end

class Base
  include A
end

class C < Base
  include B
  def initialize
    aye = A.dup
    self.class.include aye
  end
end

c = C.new
puts c.salutations

#=> a

当然,如果要克隆的模块以后要修改,则此方法将无效。