3

我想在 Ruby 中使用委托,但我不能保证目标对象会响应我将调用的所有方法。我可以用默认行为定义委托吗?

例如

class DummyPresenter
  delegate :name, :age, :to => :@content, :default => nil
  def initialize(content)
    @content = content
  end
end

class Student
  def name
    "name"
  end
end    

> DummyPresenter.new(Student.new).age # => nil
> DummyPresenter.new(Student.new).name # => "name"

现在,上面的例子会引发:

NoMethodError:
   undefined method `age' for #<Student:0xa121212>
4

4 回答 4

4
def method_missing(method, *args)
  if @content.respond_to? method
    @content.send method, *args
  else
    #your default behaviour (or super)
  end 
end

你也可以使用 DelegateClass 它会做同样的事情。

于 2012-06-25T12:01:01.850 回答
2

我发现将方法委托给原始对象的最简单方法是使用 SimpleDelegator(在 stdlib 中提供)

class Presenter < SimpleDelegator

  def initialize model
    super model
  end

  def foo
    'bar'
  end
end

class Person
  def bam
    'baz'
  end
end

person = Person.new
presenter = Presenter.new Person

presenter.foo # => 'bar'
presenter.bam # => 'baz'

从文档:

SimpleDelegator 类提供了将所有支持的方法调用委托给传递给构造函数的对象的方法

于 2014-02-21T21:33:49.483 回答
0

最后我使用了define_method

class DummyPresenter

  @@delegated_methods = [:name, :age]
  @@delegated_methods.each do |method|
    define_method(method) do
      return @content.try(method) if @content.respond_to?(method)
      nil
    end
  end

 def initialize(content)
   @content = content
 end

结尾

于 2012-06-25T12:51:18.160 回答
0

不使用委托并像这样手动执行如何?

class DummyPresenter
  def initialize content; @content = content end
  def name; @content.respond_to?( :name ) ? @content.name : dflt_name end
  def age; @content.respond_to?( :age ) ? @content.age :dflt_age end
  def to; @content.respond_to?( :to ) ? @content.to :dflt_to end
  def dflt_name
    nil # or whathever code
  end
  def dflt_age; nil end
  def dflt_to; nil end
end

否则你必须重新编程委托方法,我认为......

于 2012-06-25T11:49:04.127 回答