通过在另一个模块中混合来覆盖模块混合行为

我希望能够来回切换实例如何响应消息。 我希望通过混合模块,然后混合另一个模块来覆盖该行为。

例:

module Dog def speak puts "woof woof" end end module Cat def speak puts "meow" end end class Animal end 

现在我想来回切换, Animal一个实例如何响应speak信息:

 animal = Animal.new animal.extend(Cat) animal.speak animal.extend(Dog) animal.speak animal.extend(Cat) animal.speak animal.extend(Dog) animal.speak animal.extend(Cat) animal.speak 

我希望此代码输出以下内容:

 meow woof woof meow woof woof meow 

相反,它输出如下:

 meow woof woof woof woof woof woof woof woof 

有关如何使其按预期工作的任何提示?

我在Ruby中的Adapter Pattern中调整了你的另一个问题的答案:访问你的实例变量

 module Dog def speak puts "woof woof" end end module Cat def speak puts "meow" end end module Module_manager attr_accessor :name def extend mod @ancestors ||= {} return if @ancestors[mod] remove @name if @name @name = mod mod_clone = mod.clone @ancestors[mod] = mod_clone super mod_clone end def remove mod mod_clone = @ancestors[mod] mod_clone.instance_methods.each {|m| mod_clone.module_eval {remove_method m } } @ancestors[mod] = nil end end class Animal include Module_manager end animal = Animal.new animal.extend(Cat) animal.speak # meow animal.extend(Dog) animal.speak # woof woof animal.extend(Cat) animal.speak # meow animal.extend(Dog) animal.speak # woof woof animal.extend(Cat) animal.speak # meow 

我不确定以下是否回答了您的问题,但这是实现相同行为的更简单方法。

 class Animal include Dog alias :dog_speak :speak include Cat alias :cat_speak :speak private :dog_speak, :cat_speak def initialize @speak_to_me = [:cat_speak, :dog_speak].cycle end def speak send @speak_to_me.next end end animal = Animal.new #=> #> animal.speak #-> meow animal.speak #-> woof woof animal.speak #-> meow animal.speak #-> woof woof