我有一个具有实例方法的类,它返回一个哈希值。我无法直接更改该类的代码,但我可以使用模块扩展它。我需要在方法的返回哈希中添加一些新键。像这样:
class Processor
def process
{ a: 1 }
end
end
module ProcessorCustom
def process
super.merge(b: 2) # Not works :(
end
end
Processor.send :include, ProcessorCustom
processor = Processor.new
processor.process # returns { a: 1 }, not { a: 1, b: 2 }
我该怎么做?感谢。
答案 0 :(得分:5)
您可以拨打prepend
而不是include
:
Processor.prepend(ProcessorCustom)
processor = Processor.new
processor.process
#=> {:a=>1, :b=>2}
prepend
和include
导致不同的祖先顺序:
module A; end
module B; end
module C; end
B.ancestors #=> [B]
B.include(C)
B.ancestors #=> [B, C]
B.prepend(A)
B.ancestors #=> [A, B, C]
根据您的使用情况,您还可以extend
特定实例:(这不会影响其他实例)
processor = Processor.new
processor.extend(ProcessorCustom)
processor.process
#=> {:a=>1, :b=>2}
或使用SimpleDelegator
来实施decorator pattern:
require 'delegate'
class ProcessorCustom < SimpleDelegator
def process
super.merge(b: 2)
end
end
processor = ProcessorCustom.new(Processor.new)
processor.process #=> {:a=>1, :b=>2}
答案 1 :(得分:2)
我认为第一个要考虑的选择是需要读者理解最少的工作;以及面向对象的软件,它将成为专门研究超类行为的子类。如果,只有当有令人信服的理由这样做时,我才会偏离这一点。
这个怎么样?:
#!/usr/bin/env ruby
class Processor
def foo
{ x: 3 }
end
end
class MyProcessor < Processor
def foo
super.merge({ y: 7 })
end
end
p MyProcessor.new.foo # outputs: {:x=>3, :y=>7}
答案 2 :(得分:1)
我认为创建代理比污染原始类更好。
class Proxy
def initialize(target)
@target = target
end
# add some syntactic sugar
singleton_class.class_eval { alias [] new }
def process
@target.process.merge!(b: 2)
end
end
Proxy[Processor.new].process #=> {a: 1, b: 2}
您甚至可以创建自己的动态代理。
class DynamicProxy < BasicObject
def initialize(target)
@target = target
end
# again, add some syntactic sugar
singleton_class.class_eval { alias [] new }
def method_missing(name, *args, &block)
super unless @target.respond_to?(name)
# Do something before calling the target method
result = @target.send(name, *args, &block)
# Do something after calling the target method
end
def respond_to_missing?(name, include_private = false)
@target.respond_to?(name, include_private)
end
end
要隐藏创建Processor
实例的详细信息,您可以创建一个简单的工厂来处理创建。
module ProcessorFactory
def self.create
DynamicProxy[Processor.new]
end
end
然后你可以完成你的工作
ProcessorFactory.create.process