Search code examples
rubyinitializationparentsuper

ruby: calling super without having a parent class


I have a class which overrides self.new and calls super in it, but the class doesn't derive from antoher class. So what exactly does the call?

class Test
  attr_reader :blatt

  def self.new(blatt, quellformat, &block)
    begin
      # why can't I call initialize(blatt,quellformat) here? 
      # when I try this, it only prints "wrong # of arguments(2 for 1)"

      a = super(blatt, quellformat) # but this works...

      # some code
      a
    end
  end

  def initialize(blatt, quellformat)
    @name = blatt.blattname
    @datei = blatt.datei
    @blatt = blatt
    @qu = quellformat
  end
end

Solution

  • why can't I call initialize(blatt,quellformat) here?

    Because Test::new is a class method and Test#initialize is an instance method. You need an instance of your class to call initialize.

    but the class doesn't derive from another class

    It might not be obvious, but your class is actually an instance of Class.

    So what exactly does the call?

    By defining self.new, you're overriding Class#new. According to the documentation:

    Calls allocate to create a new object of class’s class, then invokes that object’s initialize method, passing it args.

    A Ruby implementation would look like this:

    def self.new(*args)
      obj = allocate
      obj.send(:initialize, *args)
      obj
    end
    

    Calling super simply invokes the default implementation, i.e. Class#new, which does the same. Here's the C code:

    VALUE
    rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
    {
        VALUE obj;
    
        obj = rb_obj_alloc(klass);
        rb_obj_call_init(obj, argc, argv);
    
        return obj;
    }