由于范围是两个端点之间的值,我们需要比较两个端点之间的值,因此我们使用比较运算符< =>,它将两个操作数进行比较并计算为-1,0或1,取决于他们的相对顺序。
其次,如果我们想要迭代,那么我们必须有一组离散的范围成员,而不是连续集。我们使用succ来创建离散范围。整数肯定是离散的。
所以我构建了一个名为Apple的类。如您所见,我定义了比较运算符方法< =>和succ方法,因为我想要一个离散范围:
class Apple
attr_accessor :val
def initialize(val)
@val = val
end
def <=>(other)
if @val > other.val
1
elsif @val == other.val
0
else
-1
end
end
def succ
val.succ
end
end
现在我创建了三个苹果,我希望得到所有苹果的范围:
a = Apple.new 1
=> #<Apple:0x00000001d3fa30 @val=1>
b = Apple.new 2
=> #<Apple:0x00000001d35210 @val=2>
c = Apple.new 3
=> #<Apple:0x00000001d2fbf8 @val=3>
(a..b).to_a
=> [#<Apple:0x00000001d3fa30 @val=2>]
嗯,出乎意料的事情发生了。我期待这个阵列包括所有三个苹果。但是,它只返回了中间的苹果。我可能做错了什么?
答案 0 :(得分:0)
首先,elsif
中您方法的比较应与==
(双等)而不是=
:
def <=>(other)
if @val > other.val
1
elsif @val == other.val
0
else
-1
end
end
但是,您不必自己编写所有比较,而是可以将@val
与<=>
进行比较,如下所示:
def <=>(other)
@val <=> other.val
end
其次,succ
方法应返回同一个类的对象,并且您似乎返回一个整数/字符串(val.succ
,其中val
分别是整数/字符串)而不是Apple
类的一个对象。所以它应该是:
def succ
Apple.new(@val + 1) # or Apple.new(@val.succ)
end
进行这些更改后,代码似乎有效:
class Apple
attr_accessor :val
def initialize(val)
@val = val
end
def <=>(other)
@val <=> other.val
end
def succ
Apple.new(@val + 1)
end
end
a = Apple.new 1
b = Apple.new 2
c = Apple.new 3
puts (a..b).to_a
#=> [#<Apple:0x007fa10a97bc08 @val=1>, #<Apple:0x007fa10a97bb18 @val=2>]
puts (a..c).to_a
#=> [#<Apple:0x007fc8d3957b28 @val=1>, #<Apple:0x007fc8d3957858 @val=2>, #<Apple:0x007fc8d3957830 @val=3>]