Suppose I have this simple class:
class Color
attr_accessor :rgb
def initialize(ary)
@rgb = ary
end
def +(other)
other = Color.new(other) unless Color === other
Color.new(@rgb.zip(other.rgb).map {|p| [p.reduce(:+), 255].min })
end
end
I know this is a bad way to implement it but this is the shortest way I can think.
c100 = Color.new([100, 100, 100])
c100 + c100 #=> Color(200, 200, 200)
c100 + c100 + c100 #=> Color(255, 255, 255)
It also works if I give an Array as Colors:
c100 + [50, 50, 50] #=> Color(150, 150, 150)
But I can’t to this:
[50, 50, 50] + c100 #=> TypeError: can't convert Color into Array
Defining coerce doesn’t work. How can I make it working?
It’s because the code
calls the
+method on Array, not Color, and that method can’t convert a color to an Array.By contrast,
does call Color’s
+method.However, even if you define a conversion method in Color:
the Array method will not work as you expect; the result will be the concatenation of the two arrays, since Array’s
+method concatenates their operands, rather than adding their elements:Here, the result will be an Array, rather than a Color.
EDIT:
The only way I see of making this work is to alias the
+method of Array to handle the special case of receiving a Color as the second operand. However, I will admit that this approach is rather ugly.