You Can’t Subclass Integers in Ruby

This post is mainly just an excuse to test a Gist plugin for WordPress.

Occasionally, you might think it would be handy to subclass Numeric types such as Integer. For instance, you might want to create a constrained integer which can only have certain values.

Ruby isn’t quite turtles all the way down, though: Numerics in Ruby are immediates, meaning that they don’t represent a heap-allocated object. Since you can’t allocate them, you can’t create a subclass and allocate instances of the subclass:

This entry was posted in Ruby and tagged , , , , , . Bookmark the permalink.
  • http://iain.nl iain

    Interesting! Do you also know why you cannot create subclasses of Class?

    • http://twitter.com/canweriotnow jason lewis

      Because you will tear a hole in the space-time continuum.

  • http://twitter.com/canweriotnow jason lewis

    Dammit, @avdi, way to make me pull up irb at 0330 -0400. That’s just mean.

    • http://avdi.org Avdi Grimm

      :-D

  • http://ekenosen.net/nick nevans

    Another interesting artifact of integers in ruby:

    irb(main):001:0> (-2..2).map {|i| i.object_id }
    => [-3, -1, 1, 3, 5]
    irb(main):002:0> true.object_id
    => 2
    irb(main):003:0> false.object_id
    => 0
    irb(main):004:0> nil.object_id
    => 4

  • http://ekenosen.net/nick nevans

    Another interesting artifact of integers in ruby:

    irb(main):001:0> (-2..2).map {|i| i.object_id }
    => [-3, -1, 1, 3, 5]
    irb(main):002:0> true.object_id
    => 2
    irb(main):003:0> false.object_id
    => 0
    irb(main):004:0> nil.object_id
    => 4

    • http://avdi.org Avdi Grimm

      That IS interesting!

      • http://chastell.net/ Piotr Szotkowski

        This is because (at least in MRI and YARV) the least significant bit of the object id says whether it’s an immediate Fixnum or not (odd object id → it’s a Fixnum, even object id → it’s some other object). This is also the reason why Fixnums on 32-bit systems are limited to 2^30-1 (of the 32 bits, one is used for the Fixnum/non-Fixnum choice, the other for the Fixnum’s sign).

        More fun (with false/true/nil/undef and symbols, as well as object_id ↔ C’s VALUE differences) at gc.c’s rb_obj_id(): https://github.com/ruby/ruby/blob/ruby_1_9_2/gc.c#L2834

        • juanfatas

          In Ruby 2.0.0-p247:

          pry(main)> (-2..2).map {|i| i.object_id }
          => [-3, -1, 1, 3, 5]
          pry(main)> true.object_id
          => 20
          pry(main)> false.object_id
          => 0
          pry(main)> nil.object_id
          => 8