我需要了解继承的帮助。
class MyArray < Array
end
a = MyArray[1, 2, 3] #=> [1, 2, 3]
b = MyArray[4, 5] #=> [4, 5]
c = a + b #=> [1, 2, 3, 4, 5]
a.class #=> MyArray
b.class #=> MyArray
c.class #=> Array
我不明白为什么加法的结果不是MyArray
类的实例。
答案 0 :(得分:5)
我不明白为什么添加后我的数组“ a”不是“ MyArray”类。
为什么要(MyArray
)?定义对数组的串联操作以返回新的Array
,所以这就是这里发生的情况。 https://ruby-doc.org/core-2.5.3/Array.html#method-i-2B
如果需要,可以在您的类中重写该操作以返回MyArray的实例。不要忘记所有其他类似的方法。
这也是为什么子类化标准集合不是一个好主意的原因。最好在这里使用合成而不是继承。
答案 1 :(得分:3)
就Sergio关于使用合成而不是继承以及在评论中进行交换的评论而言,只需添加一点即可。
您可以说MyArrayLike 具有而不是说MyArray 是。 然后,您可以“转发”对基础数组有意义的方法,但仍然添加自己的功能,该功能对于您的类没有子类化数组
是有意义的。Ruby甚至包括Forwardable模块在内,有几种方法可以使其变得非常简单。
class MyArrayLike
attr_reader :arr
def initialize( initial_arr )
@arr = initial_arr
end
def +(other)
result = self.class.new(arr + other.arr)
# maybe you want to do more than just concat the underlying array, if so you can do it here
result
end
def first
# for example maybe you want first to just return the first item in the underlying array.
arr.first
end
end
a = MyArrayLike.new([1,2,3])
b = MyArrayLike.new([4,5])
puts "a.class = #{a.class}"
# => a.class = MyArrayLike
puts a
# => #<MyArrayLike:0x00000000dc4b00>
a += b
puts "a.class = #{a.class}"
# => a.class = MyArrayLike
puts a
# => #<MyArrayLike:0x00000000dc4470>
puts a.first
# => 1
puts a.arr
# => 1
# 2
# 3
# 4
# 5
答案 2 :(得分:3)
将MyArray
添加到MyArray
以获得Array
可能是违反直觉的,但是可以定义一个方法来返回任何类。对于您正在调用的Array#+
,它恰好被定义为返回一个Array
。就是这样。
如果您希望它返回MyArray
,一种方法是如下定义MyArray#+
:
class MyArray < Array
def +other
MyArray.new(super)
end
end
(MyArray.new([1, 2, 3]) + MyArray.new([4, 5])).class # => MyArray
顺便说一下,请注意您的MyArray#initialize
定义是没有意义的,因此是多余的。