1

I admit that in duck-typing languages, abstract classes aren't used so often, so this question is more out of curiosity than of actual need:

In Ruby (at least 2.0), Fixnum and Bignum have a common superclass called Integer. It looks to me, that this is an abstract class; at least, it can't be instantiated, i.e. when you do in irb:

irb(main):047:0> Integer.new(8)
NoMethodError: undefined method `new' for Integer:Class
    from (irb):47
    from /usr/bin/irb:12:in `<main>'

Now, if I would decide to roll out my own class which behaves like Integer, i.e. being "as abstract as Integer is", how would I do this? I thought that every class contains a (hidden) new method (which calls my initialize method if present).

toro2k
  • 19,020
  • 7
  • 64
  • 71
user1934428
  • 19,864
  • 7
  • 42
  • 87
  • 1
    Go through this question http://stackoverflow.com/questions/512466/how-to-implement-an-abstract-class-in-ruby – BinaryMee Jun 24 '15 at 13:13
  • 2
    Abstract base classes with strict enforcement like this do go against the usual Ruby style. If you really, really need to be a jerk about people instantiating your class: `def initialize; raise "Nope"; end` then let subclasses redefine that. – tadman Jun 24 '15 at 16:27
  • I don't think this answers my question. Or is it possible, that Ruby's integer class raises "NoMethodError: undefined method `new'"? If this were the case, I think the stack trace would show 'initialize' as the source of the exception, wouldn't it? – user1934428 Jun 26 '15 at 08:49
  • @BinaryMee: This would also not explain the wording of the exception I got. – user1934428 Jun 26 '15 at 08:51

1 Answers1

5

You can undefine the new class method calling undef_method on the singleton class of your class, for example:

class Foo
  class << self
    undef_method(:new)
  end
end

Foo.new
# NoMethodError: undefined method `new' for Foo:Class

Or alternatively:

class Foo; end
Foo.singleton_class.send(:undef_method, :new)

Update: for the sake of completeness here's a quick (and possibly dirty) solution to the problem mentioned by @tadman in the comments. It uses the inherited method to define a new singleton method for the subclasses of Foo that mimics the implementation of Class#new:

class Foo
  class << self
    undef_method(:new)

    def inherited(subclass)
      subclass.define_singleton_method(:new) do |*args|
        obj = subclass.allocate
        obj.send(:initialize, *args)
        obj
      end
    end
  end

end

class Bar < Foo
  attr_reader :bar
  def initialize(bar)
    @bar = bar
  end
end

Bar.new('foobar').bar # => "foobar" 
toro2k
  • 19,020
  • 7
  • 64
  • 71
  • 1
    There's also the `undef` keyword. – cremno Jun 24 '15 at 13:50
  • 2
    Don't forget this will mean you need to add that back in for subclasses which could get kind of messy. – tadman Jun 24 '15 at 16:26
  • @toro2k: I think your solution is the right one. It explains at least the effect I see from instantiating an Integer. I wonder why a Ruby core class was defined as being abstract. It is a rarely used concept in duck-typing languages.... – user1934428 Jun 26 '15 at 08:54