Delegating class methods to an object in ruby

邮差的信 提交于 2020-01-04 09:12:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!