2016-04-22 74 views
1

我有一个Ruby类C,其中包括一些第三方模块,说AB在Ruby中,是否可以将模块移到祖先链上?

模块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功能采取precdence超过D:我想移动A所以它是在祖先链的D前,像这样:

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

我已经尝试只是包括A再次但这并没有工作。有没有办法做到这一点?

+0

你看过吗[莫独乐#prepend'(http://ruby-doc.org/core-2.3.0/Module.html#method-i-prepend)? – Myst

+0

P.S.我的意思是,预先加上'A',然后加上'B' ....另外 - 不会改变破坏'B'的实现(可能依赖于原始继承流程)的层次结构风险? – Myst

+0

会有这种风险,但在这种特殊情况下,我知道风险不存在。我只有这个问题,因为B包括了它不应该的东西。 – starfry

回答

2

一旦建立了mixin层次就不可能改变。只有包含顺序决定了层次结构。你必须包括AC(首次),您包括BC后,或者,如果你在前面加上AC,而不是包括它的,那么它将优先于D即使B被纳入C以后。

+0

我已经为该问题添加了一个类示例。我已经尝试了很多'include A'和'prepend A'的排列,但没有成功。 – starfry

+1

您不能在同一个类中多次包含或预先添加一个模块。正如我写的,第一次包含/预先**的时间很重要。 – sawa

+0

啊我得到你,这是**第一次**的事情。这就是我的想法,最后我得出了你确认的结论,即不能做到。 – starfry

1

当然可以。我每天都做,每周星期两次。嗯,有点...

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) } 

让我们来看看:

D.instance_methods 
    #=> [:hiya, :what_if?] 
(A.instance_methods & D.instance_methods).each { |m| D.send(:remove_method, m) } 
    #=> [:hiya] 
D.instance_methods 
    #=> [:what_if?] 
C.instance_methods.include?(:hiya) 
    #=> true 
a.hiya("Lois") 
ho Lois 
+0

我试过这个,它确实有效,但它不会改变祖先链 - 它将从模块中移除该方法,这会影响使用它的其他任何方法。有没有在'C'类范围内达到效果的方法,以便包括'D'的其他类不受影响? – starfry

+0

这就是我的意思,“好吧,有点......”。 @sawa已经解释说,祖先链不能重新排列(对你的问题的答案),所以没有什么可说的。我只是告诉你一些东西可以做到这一点,会有同样的效果,你想要什么去做。我不明白你在'C'类范围内的其他类是什么意思。类不能包含类。 –

+0

我的意思是从'D'l中删除的方法被限制在它包含在'C'类中,以便包括'D'在内的其他类不受影响。我只是想知道如果你知道某些东西,但我意识到在所有类别的祖先链中都是相同的'D',并且对'D'的改变会影响所有具有'D'作为祖先的类。 – starfry

相关问题