Can I use Forwardable to delegate a constant in Ru

2019-06-13 15:48发布

问题:

Given a class like:

class Thing
  CONSTANT = 10
  # other code
end

And another like:

class Other
  def initialize
    @thing = Thing.new
  end

  def method
    puts CONSTANT
  end
end

Is it possible to extend Forwardable to have Other's CONSTANT delegate to Thing's constant?

I have tried extendingSingleForwardable (see docs here ) like so:

class Other
  extend SingleForwardable

  def initialize
    @thing = Thing.new
  end

  def method
    puts CONSTANT
  end

  def_single_delegator :@thing, :CONSTANT
end

and:

def_single_delegator :@thing, :constant

but neither worked, am I getting the syntax wrong? If not, is there another way?

回答1:

This one is answered by the documentation (bold emphasis mine):

def_single_delegator(accessor, method, new_name=method)

Defines a method method which delegates to accessor (i.e. it calls the method of the same name in accessor). If new_name is provided, it is used as the name for the delegate method.

So, no, you can only delegate message sends, not constant lookup.



回答2:

Forwardable (and SingleForwardable) let you add class functions to your current class via a module. When you write a delegator you're specifying which methods are being passed on to the receiving object from the original module.

In your example, def_single_delegator :@thing, :CONSTANT is being interpreted as the following: Defines a method :CONSTANT which delegates to accessor :@thing (i.e. it calls the method of the same name in accessor).

As you can see, this is not passing on the value of the constant, instead it's passing on a method with the same name as the constant. If you want to pass on the same value as the constant you can provide an accessor method that returns to you the value of the original constant so that you can assign it in this class.