开发者

Ruby Object Comparable to Fixnum

I'd like to implement a class in Ruby that's comparable (using the <=> operator) with any Fixnum, and vice-versa. This will ultimately be used in a range. Here is an outline of my class:

class N
  include Compar开发者_如何学编程able
  attr :offset
  def initialize(offset = 0)
    @offset = offset
  end
  def succ
    N.new(@offset + 1)
  end
  def +(offset)
    N.new(@offset + offset)
  end
  def <=>(other)
    return @offset <=> other.offset if other.kind_of? N
    return 1  # N is greater than everything else
  end
end

def n; N.new(0); end

Now this works great when used in n..n+2 and n..999, but not in 1..n. This is due to the fact that n <=> 1 works but 1 <=> n does not (returns nil).

Is there any way I can get Fixnum to treat my N class as a comparable object? Your thoughts are appreciated :)


If you want to implement your own number type, you must implement coerce:

class N
  def coerce(other)
    return N.new(other), self
  end
end

n = N.new

1 <=> n # => -1

All of Ruby's builtin number types in the core library, all number types in the standard library, as well as all third-party number types use the coerce protocol to find a common type in order to make operators such as +, * and == commutative and -, / and <=> symmetric.

It's not quite clear to me what the semantics of N should be, so the above implementation is only an example.


Okay, I did a little monkey patching (freedom patching ;) that seems to have solved my problem for now.

class Fixnum
  def <=>(other)
    return -1 if other.kind_of? N
    return -1 if self < other
    return 0 if self == other
    return 1 if self > other
  end
end

Output seems to be as expected and it doesn't break anything in the inner workings of Fixnum as far as I can tell. Any better ideas/comments, feel free to post 'em.

1 <=> n # => -1
1 <=> 1 # => 0
1 <=> 2 # => -1
2 <=> 1 # => 1
1 == 1  # => true
1 == 2  # => false
1 < 2   # => true
1 > 2   # => false
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜