#48 Calling Superclass Constructors

brian Fri 10 Mar 2006

I checked in basic support for calling a superclass constructor:

  • if you don't provide a ctor, a public no arg make() is generated for you
  • you can explicitly call super.xxx in your constructor now
  • if you don't call a super ctor and exactly one no arg ctor available in the superclass, it will be implicitly called for you; otherwise a compiler error will be generated

In order to support the Java design it required a new fan opcode which I called CallCtor. The CallNew opcode means to allocate a new instance and call the constructor. However the CallCtor opcode means just call the constructor (instance is not allocated, but rather implicitly provided as a first argument). So a call to your superclass ctor will result in a CallCtor, while a client call to create an instance is CallNew.

This feature isn't fully functional. The following tasks are left to do:

  • ctors with default parameters
  • routing super/init calls to ctors with default parameters
  • this() constructors
  • name shortcuts
  • argument shortcuts
  • super must be first (no more than one)

The only one I will do before the compiler rewrite is handling this() - hopefully tomorrow

brian Sat 11 Mar 2006

I started digging into constructor chaining a bit more to support this, and it quickly became clear that using named constructors with a Java like design sucks ass. Consider this scenario:

class CtorBase
{
  new make(Str x) { this.x = x;  }
  new makeThis1()  { this.make("this1") }
  new makeThis2()  { make("this2") }
  Str x
}

Can you see the problem? The constructor makeThis1 can be detected as constructor chaining because it calls on "this". However look at the constructor makeThis2 - it doesn't explicitly specify "this", hence what it really means is CtorBase.make - create a new instance, not constructor chain (in fact I would automatically insert a call to super.make() for you). So I think that syntax is going to be way too confusing - plus it suffers all the problems that Java does about making it the first call in the method, etc.

So I propose we model our syntax on C# constructor chaining:

class Foo
{
  new make(Str x) { ... }
}

class Bar extends Foo
{
  new make(Str x) : super.make(x) { ... }
  new make() : this.make("x") { ... }
}

So the constructor formal parameters would be followed:

  • by a colon
  • then super or this must be specified
  • followed by dot and ctor name (omitted if calling super with same name)
  • the argument list (omitted if calling with same parameters)

What do you guys say?

andy Sat 11 Mar 2006

Using that syntax for calling super isn't bad - but its weird that I call another ctor on myself with that syntax? Not sure about that one - I see the problem though.

brian Sat 11 Mar 2006

It's pretty much the exact same syntax as C# just with a ctor name.

brian Sun 12 Mar 2006

I finished this feature up and checked it in. The only piece I did not implement is omitting the argument list - I'm not going to do that for the Java compiler. But using the C# constructor chaining syntax cleaned a bunch of stuff up since it avoids a lot of potential ambiguity. I also fixed some problems with using default arguments in constructors - they can now be used by both a client caller or through constructor chaining. Take a look at sysTest::CtorTest for the various syntax permutations.

Login or Signup to reply.