Ruby Question

How can I override Array Constructor in Ruby?

I have the following class:

class Library < Array
attr_accessor :authors
end


And I would like to initilize the authors attribute inside the constructor of the class, and still use the Array#new behaviour. I tried this:

class Library < Array
attr_accessor :authors

def initialize(**args)
@authors = {key1: 'val1', key2: 'val2'}
super(args)
end

end


But that yields an error.

How can I achieve this ?

Answer

So the #initialize override is failing because you're using object splat (**) instead of array splat (*).

But you shouldn't do this. Subclassing Ruby's core classes will lead to all sorts of counter-intuitive behavior because they have many methods that create new instances of that class -- that won't be updated to create new instances of your class. For example, Library.new.reverse and Library.new + Library.new will both return new arrays, not libraries.

Instead you can get the behavior you want by creating an array instance variable in your class and delegating to it. You can define #each and get all the Ruby enumerable methods. You can also define any array methods you want.

class Library < Array
  include Enumerable
  attr_accessor :authors

  def initialize(*args)
    @authors = {key1: 'val1', key2: 'val2'}
    @array = args
  end

  def each(&block)
    @array.each(&block)
  end

  def [](index)
    @array[index]
  end
end
Comments