Nice TWiki > Dev > CurrentDiscussions > NiceConstructors > CustomConstructors (r1.7) TWiki webs:
Dev | Doc | Main | TWiki | Sandbox
Dev . { Changes | Index | Search | Go }
Construction is the process of creating a new object whose fields have some meaningful value. Currently, only the automaticly generated default constructor does that. It takes the value of each field as a named parameter.

Basically, a custom constructor could be defined as a normal method:

class Point { double x; double y; }
Point createPoint(double angle, double distance) = new Point(x: ..., y: ...);

The problem with this solution is that a subclass can not make use of the custom constructor for its parent, since it includes the creation of the object itself, instance of the parent class. Instead, we want the a custom constructors takes the new instance (this), and sets its fields. However, this cannot be done with a normal method, since we do not want to give a way to create an uninitialized instance, as this would be unsafe (like accessing this in a Java constructor is unsafe).

Therefore, we propose to add the concept of a custom constructor. Its declaration is similar to a method default implementation, except that it has no return type, and its name is the class C being constructed, preceded by new. The parameter list is arbitrary, as is the body, except the last instruction: it must be a call of the form new(...), targetting either the automatic constructor, or another custom constructor. This guarantees that all fields are set to a correct value. The body before this last instruction can be used to compute the arguments of this last call. this is not accessible in the whole custom constructor, since it is not properly initialized.

class Point { double x; double y; }
new Point(double angle, double distance) { this(x: ..., y: ...); }

This allows to create a new point with new Point(angle: ..., distance: ...). Furthermore, a subclass can be constructed by reusing this custom constructor:

class ColoredPoint extends Point { String color; }

var ColoredPoint redOrigin = new ColoredPoint(angle: 0, distance: 0, color: "red");

A custom constructor can also reuse the parent custom constructor indirectly, through the default constructor of the child class:

ColoredPoint(double angle, double distance, int color) { this(angle: angle, distance: distance, color: ...); }

-- DanielBonniot - 01 Oct 2003

Discussion

Calling new C(...) in the constructor seems redundant since C always matches the constructor name, and misleading since we might actually be constructing a subclass. Maybe a syntax like this would work better?

ColoredPoint(double angle, double distance, int color) { new(angle: angle, distance: distance, color: ...); }

Agreed, new C(...) is not a good syntax. We are thinking about using this(...) , but new(...) is an option too.

I updated the syntax above, using this(...). Which one do you prefer: this or new? DanielBonniot

I think this(...) would be too close to Java since the rules are different. (The constructor goes at the end, and this(...) suggests super(...) which doesn't make sense for Nice. But I'll defer to folks who are actually using the language. - BrianSlesinsky

I like being able to do things before calling the parent constructor, with the caveat that "this" is unavailable. But suppose you wanted to keep a hashmap of all objects of a certain type? In Java you'd add "this" to the hashmap in the constructor, which is unsafe but useful. Perhaps there should be a second pass that's started by automatically calling an init() method (if present) after all the constructors have finished?

The generated Java code would be something like:

  this(...);
  if(no subclass or subclass is not written in Nice) { this.init(); }

-- BrianSlesinsky - 13 Dec 2003

This is already possible using initializers, though the subclass check isn't implemented yet.

let Set<Foo> allFoos = new HashSet();

class Foo
{
  {
    allFoos.add(this);
  }  
  
}

-- ArjanB - 13 Dec 2003

Do you want to require that custom constructors should be defined within the class body? I think this is a good requirement because it distinguishes them more from methods. Also, they have access to "this" which should only be available from within the class body. Finally, constructors must be declared in the same package as the class anyway (package b cannot define a constructor for a.A).

How do custom constructors relate to SuperCall? It seems they are similar. I wonder if parent constructor invocation can be defined in terms of SuperCall? In Java they use super for both. Is there a reason not to use super in Nice too?

It is not clear from the examples if we are allowed to remove the labels for the constructor parameters, but I assume so since you can't use labels if you are subclassing a Java class anyway:

ColoredPoint(double angle, double distance, int color) { new(angle, distance, color); }

Do the same restrictions apply as in SuperCall? For example, is the following legal?

class A           { A(int f) { myF = f; } 
                    int myF;
                  }
class B extends A { B(int f) { new(myF: f / 2); } // passing different value for f
                                                  // is not allowed in SuperCall

The parameter list is arbitrary, as is the body, except the last instruction: it must be a call of the form new(...), targetting either the automatic constructor, or another custom constructor. This guarantees that all fields are set to a correct value.

I think this would be more clearly (and correctly) stated as:

The parameter list is arbitrary. If the class has a superclass, then the first instruction of the body must be a call of the form new(...) targetting either another constructor in the class being defined, or a constructor in the superclass of the class being defined. Any code may follow the new(...) call as in a method implementation.

Furthermore, require that the constructor must assign a value to every field that does not have a default value defined for it in the class's body; i.e. there are no implicit defaults (like in Java where an int defaults to zero if no value is assigned to it). Or, would you like to say that if a constructor parameter has the same name as a field, then that parameter's value is automatically assigned to the field?

State that if a custom constructor is defined then the automatic constructor is not generated (true?). Explain how self-calls dispatch in constructors, if different than dispatch from method bodies. Explain the order in which initialization blocks and constructor bodies are run. Is it even necessary to have initialization blocks anymore?

-- BrianSmith - 18 Jan 2004

Topic CustomConstructors . { Edit | Attach | Ref-By | Printable | Diffs | r1.27 | > | r1.26 | > | r1.25 | More }
Revision r1.7 - 18 Jan 2004 - 20:51 GMT - BrianSmith
Parents: WebHome > CurrentDiscussions > NiceConstructors
Copyright © 1999-2003 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback.

Dev.CustomConstructors moved from Dev.NonDefaultConstructors on 01 Oct 2003 - 21:08 by DanielBonniot - put it back