从数组强制
假设我有这个简单的类:
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
我知道这是一个不好的实现方法,但这是我能想到的最短的方法。
c100 = Color.new([100, 100, 100])
c100 + c100 #=> Color(200, 200, 200)
c100 + c100 + c100 #=> Color(255, 255, 255)
如果我将数组作为颜色,它也可以工作:
c100 + [50, 50, 50] #=> Color(150, 150, 150)
但我不能这样做:
[50, 50, 50] + c100 #=> TypeError: can't convert Color into Array
定义强制
不起作用。我怎样才能让它发挥作用?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是因为代码
调用 Array 上的
+
方法,而不是 Color,并且该方法无法将颜色转换为 Array。相比之下,
确实调用 Color 的
+
方法。然而,即使你在 Color:
Array 方法中定义了转换方法,也不会像你期望的那样工作;结果将是两个数组的串联,因为 Array 的
+
方法连接它们的操作数,而不是添加它们的元素:这里,结果将是一个 Array,而不是 Color。
编辑:
我认为实现这项工作的唯一方法是为 Array 的
+
方法起别名,以处理接收 Color 作为第二个操作数的特殊情况。然而,我承认这种方法相当丑陋。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.进一步阐述@peter-o的答案,我想出了这个实现,虽然从重新定义数组的几种方法的意义上来说很丑陋,但它几乎成为了预期行为的一个很好的解决方法,我不认为我会曾经在生产代码中适应过这个,但我真的很喜欢这个挑战...很抱歉在颜色主题上存在分歧,但我不知道负数和时间的预期行为是什么。
挑战之一是确保对 Point#- 方法的反向调用不会返回意外结果,因此将 @coerced 实例变量作为对象上的控制标志。
毕竟,这段代码设法实现的是将强制功能添加到 Array 类中不存在的地方,显式添加到方法
Array#+
、Array#-
和 <代码>数组#*。Elaborating further on @peter-o answer I came up with this implementation that, although uggly in the sense that it redefines several methods of Array, it pretty much manages to be a good workaround for the expected behaviour, I don't think I would ever fit this in production code but I really liked the challenge... Sorry for diverging on the color subject but I didn't know what the expected behaviour for minus and times would be.
One of the chalenges was to make sure the inverted call on the
Point#-
method would not return unexpected results, hence the@coerced
instance variable as a control flag on the object.After all, what this code manages to achieve is adding coerce functionality to the Array class where it didn't exist, explicitly to methods
Array#+
,Array#-
andArray#*
.