我有以下类(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/