我有:
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
?
答案 0 :(得分:1)
你可以使用前置方法通过鸭子输入传递给[]方法的参数来非侵入性地覆盖Array中的[]方法,然后调用原来的,如果它不是你的期望。那么你根本不需要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>'
答案 1 :(得分:1)
只需考虑消息和接收器。
@array[position_array]
将消息[]
发送给接收方@array
。 @array
是Array
的一个实例,因此调用方法Array#[]
。
self[position_array]
将消息[]
发送给接收方self
。在实例方法中,self
指的是该实例。由于self
是Thing
的实例,因此调用方法Thing#[]
。
由于Thing
是Object
的子类而不是Array
的子类(这里没有错,所以你不应该继承Array
),你的[]
的实现{1}} 不覆盖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