Reputation: 777
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
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