Re: Re: Constructors?

Daniel Bonniot <[email protected]> Sat, 09 Oct 2004 12:51:17 +0200
Newsgroups gmane.comp.lang.nice.general
Message-ID <[email protected]>
> So, C# initializes everything first then calls the constructors.  Now C#
> imposes a restriction that Java does not have such that initializers
> cannot call methods, int y = getSomeVal(), since this would create a
> situation in which uninitialized variables could be accessed.

OK, thanks for the research. So C# has an additional restriction that ensures 
that field initialization does not fail, but that does not solve the general 
problem. I adapted the example to C#, and it fails in the same way:


// C#
using System;

public class Parent {
   public Parent() {
     // We want to log the construction of Parent objects
     Console.WriteLine("Instance created: " + this);
   }

   public override string ToString() {
      return "Parent";
   }
}

class Child : Parent {
   /** @name a non-null name */
   public Child(string name) {
     this.name = name;
   }

   private string name;

   public override String ToString() {
     return "Child, with name length: " + name.Length;
   }

   // Trying it out...
   static void Main(string[] args) {
     new Parent();
     new Child("Georges");
   }
}


I tried it with mono, and that gives:


Instance created: Parent

Unhandled Exception: System.NullReferenceException: Object reference not set 
to an instance of an object
in <0x00019> Child:ToString ()
in <0x0004f> System.String:Concat (object,object)
in <0x0001a> Parent:.ctor ()
in <0x0000a> Child:.ctor (string)
in <0x0003f> Child:Main (string[])


So C# has made some progress, but it still has holes. The equivalent program 
in Nice works without problem:


public class Parent {

   {
     // We want to log the construction of Parent objects
     println("Instance created: " + this);
   }

   toString() {
      return "Parent";
   }
}

class Child extends Parent {
   String name;

   toString() {
     return "Child, with name length: " name.length;
   }
}

void main(String[] args) {
   let p = new Parent();
   let c = new Child(name: "Georges");
}


gives:


Instance created: Parent
Instance created: Child, with name length: 7


(note that you need a development version to get this result, since the 
correct implementation of initialization order had been post-poned. this was 
the occasion for me to finish it ;-)

This illustrates why code that makes use of 'this' cannot be allowed to run 
until all the constructors have executed (which guarantees all fields are set 
as wanted). Hence the distinction between two phases: creation and initialization.


>> I see two things that could be improved to make Nice's approach
>> easier to use:
>>
>> 1) In the special case of a class without any fields, the call to 
>> 'this()' should not be necessary. That would solve the problem you 
>> initially reported.
> 
> 
> Or classes without any non-initialized fields.

Right.

>> 2) Instead of requiring a call to this(x: valueX, y: valueY), we
>> could also allow constructor bodies that definitely assign a value to
>> this.x and this.y, while still not allowing using the 'this' value.
>> This would provide a more familiare syntax, with exactly the same
>> safety properties.
> 
> 
> I'm not sure I follow, so the following would be legal:
> 
> class A
> {
>   int x;
>   new A()  // I know this syntax does not exist, YET! :)
>   {
>     x = 5;
>   }
> }

Yes.

Note that you can write this specic example equivalently and more simply:

   class A { int x = 5; }

:-)

> What would be illegal?

class A
{
   String name;
}

new A()
{
}

This would be illegal since name would not be assigned any value.

Cheers,

Daniel


-------------------------------------------------------
This SF.net email is sponsored by: IT Product Guide on ITManagersJournal
Use IT products in your business? Tell us what you think of them. Give us
Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more
http://productguide.itmanagersjournal.com/guidepromo.tmpl