#21 Class, mixin, constructor syntax

brian Fri 30 Dec 2005

If we assume the mixin design for multiple inheritance, then the next step is to design the syntax for defining classes, mixins, constructors, and scoped super calls. The constructor issue is especially tricky without the ability to overload methods by parameter - it practically forces us to have "named constructors", which is going to be a bit foreign to the C-like crowd. But making constructors be normal static like methods is actually much OO - send a message (via the standard dot operator) to the class itself to instantiate an object. Plus I like unifying the syntax for calling a static factory method versus a constructor - in both cases they should look to the client like a static call on the class.

mixin Alpha 
{
  Str a1() { ... }
  virtual Void a2() { ... }
}

mixin Beta
{
  Str b1() { ... }
  abstract Obj b2()
}

class Charlie
{
  new make(Str name) { this.name = name }
  Str name
}

class Delta
  extends Charlie
  mixin Alpha, Beta
{
  new make(Str name) { super }
  protected new makeUnnamed()  { super.make("unnamed") }
  override Void a2() { super ... }
  override Obj b2()  { return Charlie.make("b2") }
}

The above example illustrates a bunch of concepts:

  1. The keyword mixin is used to define a mixin type, and to include a mixin in a class definition.
  2. The extends keyword is used to extend zero or one class (not a mixin). If zero then sys::Obj is assumed.
  3. Must use virtual keyword to make a method virtual
  4. Must use override keyword to override abstract or virtual method
  5. Constructors are named methods that use the new keyword and have an implied return type of the declaring class.
  6. Invoking a constructor method looks like invoking a static method
  7. Convention is to use "make" as the name of constructor methods. If more than one make is provided, the most commonly used one should be called "make", and others should be "makeFooBar" with a qualifying remark.
  8. Constructors are treated like static methods with regards to overloading, that is they may overload "make" or other names with incompatible signatures, although good design would be to follow the super class's signature pattern

What keyword should a mixin use to implement other mixins? In Java an interface "extends" other interfaces, but I've always thought that was sort of weird. My instinct is to use mixin, but then you get something like this:

mixin A mixin B, C {}

Which seems odd compared to (although semantically confusing):

mixin A extends B, C {}

Of course we could burn a new keyword (which I always hate to do):

mixin A include B, C {}
class D include A {}

Or just get rid of keywords altogether:

mixin A <- B, C
class D <- A

What do you guys vote?

andy Fri 30 Dec 2005

Either use extends or Ruby style D < a

Login or Signup to reply.