使用自定义类创建离散范围

时间:2015-02-08 19:29:31

标签: ruby

由于范围是两个端点之间的值,我们需要比较两个端点之间的值,因此我们使用比较运算符< =>,它将两个操作数进行比较并计算为-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>] 
嗯,出乎意料的事情发生了。我期待这个阵列包括所有三个苹果。但是,它只返回了中间的苹果。我可能做错了什么?

1 个答案:

答案 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>]