tushortz
tushortz

Reputation: 5015

Override `[]=` method in ruby array

I have a class CustomArray:

class CustomArray < Array
  def initialize(row, col)
    @row = row
    @col = col
    @array ||= Array.new(size=row * col)
  end
end

How can I override the []= method of CustomArray? I did:

class CustomArray < Array
  def []=(length, row, col)
    puts @array[0], col, row
  end
end

Regardless of a change I make to @array, the new instantiated array length remains zero.

I tried replacing the value of self, but it looks like self is read only.

Upvotes: 0

Views: 800

Answers (1)

Stefan
Stefan

Reputation: 114158

You don't need an @array instance variable when subclassing Array – each instance already is an array.

Assuming that you are trying to implement a two-dimensional array on top of the build-in (one-dimensional) Array, something like this should work:

class CustomArray < Array
  def initialize(rows, cols)
    @rows = rows
    @cols = cols
    super(rows * cols)
  end

  def []=(row, col, value)
    super(row * @rows + col, value)
  end

  def [](row, col)
    super(row * @rows + col)
  end
end

However, Ruby's core classes are heavily optimized and subclassing them can be quite tricky (see https://words.steveklabnik.com/beware-subclassing-ruby-core-classes).

Therefore, it's usually easier to use composition instead of inheritance, i.e. do use an @array instance variable, but don't inherit from Array, e.g.:

class CustomArray
  def initialize(rows, cols)
    @rows = rows
    @cols = cols
    @array = Array.new(rows * cols)
  end

  def []=(row, col, value)
    @array[row * @rows + col] = value
  end

  def [](row, col)
    @array[row * @rows + col]
  end
end

Upvotes: 4

Related Questions