我正在学习adapter pattern在 ruby 中的实现。我想访问适配器模块定义中的实例变量。看一下下面的代码:
module Adapter
module Dog
def self.speak
# I want to access the #name instance variable from my Animal instance
puts "#{name} says: woof!"
end
end
module Cat
def self.speak
# I want to access the #name instance variable from my Animal instance
puts "#{name} says: meow!"
end
end
end
class Animal
attr_accessor :name
def initialize(name)
@name = name
end
def speak
self.adapter.speak
end
def adapter
return @adapter if @adapter
self.adapter = :dog
@adapter
end
def adapter=(adapter)
@adapter = Adapter.const_get(adapter.to_s.capitalize)
end
end
为了测试它,我做了以下操作:
animal = Animal.new("catdog")
animal.adapter = :cat
animal.speak
我希望它返回以下内容:
catdog says: meow!
相反,它说:
Adapter::Cat says: meow!
有关如何从适配器模块访问 Animal#name
实例方法的任何提示?我认为问题在于我的适配器方法是类级方法。
谢谢!
最佳答案
您需要使用您的模块作为 mixin 并提供一种方法来跟踪哪个模块处于事件状态,这些方法似乎不会通过重新包含或重新扩展而被覆盖,因此我采用了我发现的扩展和删除方法 here 。
module Adapter
module Dog
def speak
puts "#{name} says: woof!"
end
end
module Cat
def speak
puts "#{name} says: meow!"
end
end
def extend mod
@ancestors ||= {}
return if @ancestors[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 Adapter
attr_accessor :name, :adapter
def initialize(name)
@name = name
@adapter = Adapter::Dog
extend Adapter::Dog
end
def adapter=(adapter)
remove @adapter
extend Adapter::const_get(adapter.capitalize)
@adapter = Adapter.const_get(adapter.capitalize)
end
end
animal = Animal.new("catdog")
animal.speak # catdog says: woof!
animal.adapter = :cat
animal.speak # catdog says: meow!
animal.adapter = :dog
animal.speak # catdog says: woof!
关于ruby - ruby 中的适配器模式 : Accessing Your Instance Variables,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41861791/