问题
I am trying to wrap calls to a singleton in a class (because I do not want the rest of the code to know that they are talking to a singleton), and I looked at the delegate module.
In my code, I have something like this:
class HideSingleton
@@obj = SingletonClass.instance # x is an instance of SingletonClass
# I want to be able to say HideSingleton.blah,
# where 'blah' is instance method of SingletonClass instance (i.e., 'x')
SimpleDelegator.new @@obj.field
end
class SingletonClass < BaseClass
attr_reader :field
def initialize
@field = SimpleDelegator.new super(BaseClass Constructor params)
end
end
Then in irb:
> require 'singleton_class'
> x = SingletonClass.new
> x.blah # 'blah' is a method that is present in BaseClass instance
> require 'hide_singleton'
> y = HideSingleton
How can I do y.blah
?
回答1:
I think there is a simpler implementation of what you are trying to do, but to accomplish the hidden singleton class that delegates to a singleton class, you can do the following:
require 'delegate'
require 'forwardable'
class BaseClass
def blah
puts 'hi'
end
end
class SingletonClass < BaseClass
attr_reader :field
def initialize
@field = SimpleDelegator.new(BaseClass.new)
end
end
class HideSingleton
def self.obj
@@obj ||= SingletonClass.new.field
end
def self.method_missing *args
obj.send *args
end
end
You can then make the following calls:
x = SingletonClass.new
x.blah
hi
=> nil
HideSingleton.blah
hi
=> nil
回答2:
There are some gotchas to be aware of:
HideSingleton Class itself still has several methods (from Object and Module) and those methods would be called on HideSingleton, not SingletonClass. For example, if we had different constants in the classes like this:
class SingletonClass < BaseClass
SingletonConst = :foo
end
class HideSingleton
HideConst = :bar
end
Then calling the class method constants on both classes results in:
SingletonClass.constants
#=> [:SingletonConst]
HideSingleton.constants
#=> [:HideConst]
The same is true for any of the standard methods (const_get, class_eval, dup, respond_to?, etc). To avoid this you would need to unload the the methods in HideSingleton that you wanted to pass through to SingletonClass (or explicitly forward them).
来源:https://stackoverflow.com/questions/4997990/delegating-class-methods-to-an-object-in-ruby