我想调用Singleton Object的方法而不引用它的实例
SingletonKlass.my_method
而不是
SingletonKlass.instance.my_method
我想出了这个解决方案(在课堂上使用method_missing):
require 'singleton'
class SingletonKlass
include Singleton
def self.method_missing(method, *args, &block)
self.instance.send(method, *args)
end
def my_method
puts "hi there!!"
end
end
这有什么缺点吗? 还有更好的解决方案吗? 你的任何推荐?
谢谢。更新:
我的目标是让一个模块与单身类混合:
module NoInstanceSingleton
def method_missing(method, *args)
self.instance.send(method, *args)
end
end
然后在课堂上使用它:
class SingletonKlass
include Singleton
extend NoInstanceSingleton
def method1; end
def method2; end
...
def methodN; end
end
我希望能够直接致电:
SingletonKlass.method1
答案 0 :(得分:12)
使用forwardable和def_delegators:
require 'singleton'
require 'forwardable'
class SingletonKlass
include Singleton
class << self
extend Forwardable
def_delegators :instance, :my_method
end
def my_method
puts "hi there!!"
end
end
SingletonKlass.my_method
修改:如果您想要包含自己定义的所有方法,可以
require 'singleton'
require 'forwardable'
class SingletonKlass
include Singleton
def my_method
puts "hi there!!"
end
class << self
extend Forwardable
def_delegators :instance, *SingletonKlass.instance_methods(false)
end
end
SingletonKlass.my_method
答案 1 :(得分:2)
method_missing
解决方案存在的问题是,如果instance
上没有该名称的方法,则只会将调用重定向到SingletonKlass
,如果人们想要这会导致问题例如,通过您提供的此接口访问instance.__id__
。以正常方式访问SingletonKlass.instance
没有太大问题,但如果你真的想要创建一个快捷方式,那么最安全的就是常量:
KlassInstance = SingletonKlass.instance
如果要动态定义常量,请使用Module#const_set
:
const_set :KlassInstance, SingletonKlass.instance
你也可以延伸。例如,您可以创建一个方法来为您创建这样的常量:
def singleton_constant(singleton_class)
const_set singleton_class.name, singleton_class.instance
end
当然,因为Module#const_set
是模块的方法,所以这种特定技术只能在模块或类的上下文中执行。另一种可能性是使用带有重载钩子方法的mixin模块:
module SingletonInstance
def included(base_class)
const_set base_class.name, base_class.instance
super
end
end
答案 2 :(得分:1)
这是一个替代方案,并不属于我的第一个答案范围。您可以创建一个mixin模块,该模块取消定义基类的所有方法,然后使用method_missing
技术:
module SingletonRedirect
def included(base_class)
instance = base_class.instance
base_class.class_eval do
methods.each &undef_method
define_method :method_missing do |name, *arguments|
instance.public_send name, *arguments
end
end
end
end
为了实现这个想法,instance
是一个局部变量,通过闭包传递给调用Class#class_eval
和Module#define_method
的块。然后,我们不需要通过base_class.instance
来引用它,因此我们可以清除所有方法,包括那个方法(一种称为空白平板的技术)。然后,我们定义一个方法重定向系统,该系统利用平坦范围将instance
称为变量,并仅调用通过Object#public_send
公开提供的方法。
答案 3 :(得分:0)
而不是SingletonKlass
,我将使用名称UrlHelper
作为更具体的示例。
require 'singleton'
class UrlHelperSingleton
include Singleton
def my_method
...
end
end
UrlHelper = UrlHelperSingleton.instance
# then elsewhere
UrlHelper.my_method
答案 4 :(得分:-1)
为什么不使用“静态”课程? e.g:
class StaticKlass
class << self
def method1; end
def method2; end
...
def methodN; end
end
end
StaticKlass.method1