Crixx93
Crixx93

Reputation: 777

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 ?

Upvotes: 4

Views: 1124

Answers (1)

Jack Noble
Jack Noble

Reputation: 2098

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
  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

Upvotes: 3

Related Questions