Cho*_*ett 11 ruby class-method instance-method
在Ruby中,假设我有一个类Foo允许我对我的大量Foos进行编目.所有Foos都是绿色和球形的,这是一个基本的自然法则,所以我定义了类方法如下:
class Foo
  def self.colour
    "green"
  end
  def self.is_spherical?
    true
  end
end
Run Code Online (Sandbox Code Playgroud)
这让我做到了
Foo.colour # "green"
Run Code Online (Sandbox Code Playgroud)
但不是
my_foo = Foo.new
my_foo.colour # Error!
Run Code Online (Sandbox Code Playgroud)
尽管事实上my_foo是明显的绿色.
显然,我可以定义一个colour调用的实例方法self.class.colour,但是如果我有很多这样的基本特征,那就很难实现.
我也可以通过定义method_missing为任何缺失的方法尝试类来做到这一点,但我不清楚这是我应该做的事情还是丑陋的黑客,或者如何安全地进行(特别是因为我实际上在ActiveRecord下在Rails中,我理解用method_missing做一些Clever Fun Stuff).
你会推荐什么?
Way*_*rad 23
Ruby附带的Forwardable模块可以很好地完成这项工作:
#!/usr/bin/ruby1.8
require 'forwardable'
class Foo
  extend Forwardable
  def self.color
    "green"
  end
  def_delegator self, :color
  def self.is_spherical?
    true
  end
  def_delegator self, :is_spherical?
end
p Foo.color                # "green"
p Foo.is_spherical?        # true
p Foo.new.color            # "green"
p Foo.new.is_spherical?    # true
Run Code Online (Sandbox Code Playgroud)
        Vad*_*rov 11
如果它是普通的Ruby,那么使用Forwardable就是正确的答案
如果它是Rails,我会使用委托,例如
class Foo
  delegate :colour, to: :class
  def self.colour
    "green"
  end
end
irb(main):012:0> my_foo = Foo.new
=> #<Foo:0x007f9913110d60>
irb(main):013:0> my_foo.colour
=> "green"
Run Code Online (Sandbox Code Playgroud)
        您可以定义一个直通设施:
module Passthrough
  def passthrough(*methods)
    methods.each do |method|
      ## make sure the argument is the right type.
      raise ArgumentError if ! method.is_a?(Symbol)
      method_str = method.to_s
      self.class_eval("def #{method_str}(*args) ; self.class.#{method_str}(*args) ; end")
    end
  end
end
class Foo
  extend Passthrough
  def self::colour ; "green" ; end
  def self::is_spherical? ; true ; end
  passthrough :colour, :is_spherical?
end
f = Foo.new
puts(f.colour)
puts(Foo.colour)
Run Code Online (Sandbox Code Playgroud)
我通常不喜欢使用eval,但在这里它应该非常安全。
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           5569 次  |  
        
|   最近记录:  |