ruby - 将属性方法委托(delegate)给父对象

标签 ruby delegation

我有以下类(class):

class Alphabet

  attr_reader :letter_freqs, :statistic_letter

  def initialize(lang)
    @lang = lang
    case lang
    when :en
      @alphabet = ('A'..'Z').to_a
      @letter_freqs = { ... }
    when :ru
      @alphabet = ('А'..'Я').to_a.insert(6, 'Ё')
      @letter_freqs = { ... }
    ...
    end
    @statistic_letter = @letter_freqs.max_by { |k, v| v }[0]
  end

end

foo = Alphabet.new(:en)

这里的核心成员是@alphabet

我想让它成为某种容器类来直接调用 Array 方法

foo[i]
foo.include?

而不是显式访问 @alphabet:

foo.alphabet[i]
foo.alphabet.include?  

我知道我可以定义很多方法,比如

def [](i)
  @alphabet[i]
end

但我正在寻找“继承”它们的正确方法。

最佳答案

您可以使用 Forwardable (它包含在 Ruby 标准库中):

require 'forwardable'

class Alphabet

  extend Forwardable
  def_delegators :@alphabet, :[], :include?

  def initialize
    @alphabet = ('A'..'Z').to_a
  end

end

foo = Alphabet.new

p foo[0]           #=> "A"
p foo.include? 'ç' #=> false

如果您希望委托(delegate)您的类未定义的所有方法,您可以使用 SimpleDelegator (也在标准库中);它允许您将实例未响应的所有方法委托(delegate)给 __setobj__ 指定的对象:

require 'delegate'

class Alphabet < SimpleDelegator

  def initialize
    @alphabet = ('A'..'Z').to_a
    __setobj__(@alphabet)
  end

  def index
    'This is not @alphabet.index'
  end

end

foo = Alphabet.new

p foo[0]           #=> "A"
p foo.include? 'ç' #=> false
p foo.index        #=> "This is not @alphabet.index"

当委托(delegate)不需要是动态的时,您可以将主类安排为 DelegateClass 的子类,将要委托(delegate)的类的名称作为参数传递并调用 super 在主类的#initialize方法中传递要委托(delegate)的对象:

class Alphabet < DelegateClass(Array)

  def initialize
    @alphabet = ('A'..'Z').to_a
    super(@alphabet)
  end

有关 Ruby 中委托(delegate)设计模式的更多信息 here

关于ruby - 将属性方法委托(delegate)给父对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20072649/

相关文章:

objective-c - 从 Objective-C 访问 Swift Delegate 的正确方法是什么?

oop - 关于授权

html - 为什么 Nokogiri 会删除内容?

ruby-on-rails - Rails sum 方法返回未定义

javascript - 就绪函数内的委托(delegate)函数

快速委派

properties - Kotlin:如何获取成员属性的委托(delegate)类?

ruby - 使用 Ruby Savon 验证针对 WSDL 的 XML 响应

ruby-on-rails - Ruby on Rails : can I use http basic auth in constraints?

html - 在 Sinatra 请求之间共享 Ruby 变量