在ruby中将类方法委托给对象

在ruby中将类方法委托给对象,ruby,design-patterns,jruby,Ruby,Design Patterns,Jruby,我试图在类中封装对单例的调用(因为我不想让代码的其余部分知道它们正在与单例对话),并且我查看了委托模块 在我的代码中,我有如下内容: 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 Sing

我试图在类中封装对单例的调用(因为我不想让代码的其余部分知道它们正在与单例对话),并且我查看了委托模块

在我的代码中,我有如下内容:

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

我该怎么做呢?

我认为有一个更简单的实现来实现您要做的事情,但是要完成委托给单例类的隐藏单例类,您可以执行以下操作:

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

有一些问题需要注意:

HideSingleton类本身仍然有几个方法(来自对象和模块),这些方法将在HideSingleton而不是SingletonClass上调用。例如,如果类中有不同的常量,如下所示:

class SingletonClass < BaseClass
  SingletonConst = :foo
end

class HideSingleton
  HideConst = :bar
end

对于任何标准方法(const_get、class_eval、dup、respond_to?)也是如此。为了避免这种情况,您需要卸载HideSingleton中希望传递给SingletonClass(或显式转发)的方法。

在您的irb示例中,您的意思是
x=SingletonClass.instance
?假设您使用的是singleton stdlib。没错,请编辑我的问题以反映这一点。那么
SingletonClass
包括
singleton
?或者是
基类
?基类->无单例。SingletonClass->基类的子类,但包括Singleton。我听说这是推荐的方法。对不起,我想我应该把我的问题说得更清楚一点。我试图将所有内容都委托给Singleton类,所以def_委托人可能不合适?根据我给您的这些新信息,您有什么建议?我做了一个简单的修改,以便您可以使用HideSingleton类上缺少的方法_来委托给delegator对象。非常感谢。漂亮的解决方案。还有一个问题:我听说method_missing比调用常规方法慢一个数量级。。。如果我希望经常使用这段代码(比如rails中的每个HTTP请求),这会带来明显的性能差异吗?可能不会,但如果您担心性能,我建议您对此进行基准测试。如果您发现缺少的方法实际上是一个明显的差异,那么您必须显式定义要委托的方法,在这种情况下,您不能简单地说:将所有内容委托给另一个类,您必须显式地说每个方法都委托给特定的委托者。一般来说,只要您没有为委托定义特定的方法,您就在使用方法\u。
x = SingletonClass.new
x.blah
hi
=> nil
HideSingleton.blah
hi
=> nil
class SingletonClass < BaseClass
  SingletonConst = :foo
end

class HideSingleton
  HideConst = :bar
end
SingletonClass.constants
  #=> [:SingletonConst]

HideSingleton.constants
  #=> [:HideConst]