Delegate attribute methods to the parent object

delegation, ruby

Solution

You can use `Forwardable` (it is included in the Ruby standard library):

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

If you wish to delegate all the methods not defined by your class you can use `SimpleDelegator` (also in the standard library); it lets you delegate all the methods that are not responded by the instance to an object specified by `__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"

When the delegate doesn't need to be dynamic you can arrange the master class to be a subclass of `DelegateClass`, passing the name of the class to be delegated as argument and calling `super` passing the object to be delegated in the `#initialize` method of the master class:

class Alphabet < DelegateClass(Array)

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

More info about the delegation design pattern in Ruby here

Problem

I have the following 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) ``` The central member here is `@alphabet`. I'd like to make it some sort of a container class to invoke Array methods directly like ``` foo[i] foo.include? ``` instead of explicitly accessing `@alphabet`: ``` foo.alphabet[i] foo.alphabet.include? ``` I know I could define a lot of methods like ``` def [](i) @alphabet[i] end ``` but I'm looking for a proper way of "inheriting" them.

Original source