Зачем индексировать себя вместо переменной экземпляра в методе скобок - PullRequest
0 голосов
/ 23 мая 2018

У меня есть:

class Thing
  def initialize
    @array = [[0, 0, 0], [1, 1, 1]]
  end
end

thing = Thing.new

Обычный способ доступа к элементу в @array состоит в использовании [] как в:

@array[0][1] # => 0

Я пытаюсь перезаписать [] чтобы получить такие результаты:

position_array = [0, 1]
@array[position_array] # => 0

Это моя попытка:

class Thing
  def [](position_array)
    index_row, index_col = position_array
    @array[index_row][index_col]
  end

  def get_value(position_array)
    @array[position_array]           # doesn't work
    # self[position_array]           # does work
  end
end

thing.get_value([0, 1])
# >> 'get_value': no implicit conversion of Array into Integer (TypeError)

Зачем мне индексировать объект Thing, чтобы индексировать @array

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Просто представьте себе сообщение и получатель .

@array[position_array] отправляет сообщение [] получателю @array.@array является экземпляром Array, поэтому вызывается метод Array#[].

self[position_array] отправляет сообщение [] получателю self.В методах экземпляра self относится к этому экземпляру.И поскольку self является экземпляром Thing, вызывается метод Thing#[].

Поскольку Thing является подклассом Object, а не подклассом Array (здесь нет ничего плохоговы все равно не должны создавать подкласс Array), ваша реализация [] делает не переопределением Array#[].Оба метода полностью независимы друг от друга, как String#[] или Hash#[].

Вот как я бы подошел:

class Thing
  def initialize
    @array = [[1, 2, 3], [4, 5, 6]]
  end

  def [](i, j)
    @array[i][j]
  end
end

thing = Thing.new
thing[0, 1] #=> 2
thing[1, 1] #=> 5
0 голосов
/ 23 мая 2018

Вы могли бы использовать предопределенный метод для неинвазивного переопределения метода [] в массиве, вводя утка в параметр, переданный методу [], а затем вызывая оригинал, если он не тот, который вы ожидаете,Тогда вам вообще не нужен объект Thing.

module MyArrayExtension
  def [] (*param)
    if param.size == 2
      row, col = param
      raise ArgumentError, 'Row must be an integer' if row.class != Integer
      raise ArgumentError, 'Column must be an integer' if col.class != Integer
      raise ArgumentError, "Element at row #{row} is not an array" if self[row].class != Array
      self[row][col]
    else
      super
    end
  end
end

class Array
  prepend MyArrayExtension
end

thing = [[1,2,3],[4,5,6]]
puts "The 2D array is: #{thing}"
puts "Extension used on the thing to get at element 1 of first array:"
puts thing[0,1]

puts '-' * 20

normal = [1,2,:blah,4,5]
puts "Normal array is #{normal}"
puts "Original [] method used to get the 3rd element:"
puts normal[2]

puts '-' * 20
puts "Using the extension on the non-2D array:"
puts normal[0,1]

Вывод этой программы:

The 2D array is: [[1, 2, 3], [4, 5, 6]]
Extension used on the thing to get at element 1 of first array:
2
--------------------
Normal array is [1, 2, :blah, 4, 5]
Original [] method used to get the 3rd element:
blah
--------------------
Using the extension on the non-2D array:
./test.rb:9:in `[]': Element at row 0 is not an array (ArgumentError)
    from ./test.rb:35:in `<main>'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...