Constructor referring to variable in Parent class.

2,369 views
Skip to first unread message

Edouard Tavinor

unread,
Feb 1, 2013, 6:36:35 AM2/1/13
to mi...@dartlang.org
okay, i have the following code:

void main() {
  Child c = new Child("bob", 3);
  
}
 

class Parent {
  int id;
}

class Child extends Parent {
  String name;
  
  Child._intern(this.name, this.id);
  
  factory Child(String name, int id) {
    Child c = new Child._intern(name, id);
  }
}

The editor (version 0.2.10_r16761) tells me that it 'Could not match parameter initializer this.id with any field', and Dartium says: 'Error: line 16 pos 33: unresolved reference to instance field 'id'
  Child._intern(this.name, this.id);' Is this the intended behaviour? If I change the code to:

void main() {
  Child c = new Child("bob", 3);
  
}
 

class Parent {
  int id;
}

class Child extends Parent {
  String name;
  
  Child._intern(this.name);
  
  factory Child(String name, int id) {
    Child c = new Child._intern(name);
    c.id=id;
  }
}


Everything works fine :)

Thanks!

Ed

Ladislav Thon

unread,
Feb 1, 2013, 6:58:25 AM2/1/13
to mi...@dartlang.org
class Parent {
  int id;
}

class Child extends Parent {
  String name;
  
  Child._intern(this.name, this.id);
  
  factory Child(String name, int id) {
    Child c = new Child._intern(name, id);
  }
}

You can only use fields from the "current" class as initializing formals. Chapter 7.6.1 of the specification says exactly: It is a compile-time error if id is not the name of an instance variable of the immediately enclosing class. (Well, the PDF form says it a little bit different than the HTML form, but whatever...)

Meaning that you have to use the parent's constructor for that.

class Parent {
  int id;

  Parent(this.id);
}

class Child extends Parent {
  String name;

  Child(this.name, int id) : super(id);
}

LT

Edouard Tavinor

unread,
Feb 1, 2013, 7:08:25 AM2/1/13
to mi...@dartlang.org
Thanks for the reply! What's the reason for this btw? I can't see what problem is avoided by adding this restriction.

Ed

Ladislav Thon

unread,
Feb 1, 2013, 7:12:27 AM2/1/13
to mi...@dartlang.org
What's the reason for this btw? I can't see what problem is avoided by adding this restriction.

I can imagine it can clash with parent's constructors... but I'm not sure, really.

LT

Edouard Tavinor

unread,
Feb 1, 2013, 7:19:59 AM2/1/13
to mi...@dartlang.org
Okay, thanks!

Lasse R.H. Nielsen

unread,
Feb 1, 2013, 10:04:07 AM2/1/13
to mi...@dartlang.org
On Fri, Feb 1, 2013 at 1:08 PM, Edouard Tavinor <edouard...@gmail.com> wrote:
Thanks for the reply! What's the reason for this btw? I can't see what problem is avoided by adding this restriction.

In Dart, fields don't really have names. They are unnamed slots of memory where a value can be stored.
The name it's declared with is instead the name of the automatically generated getter and setter (if not final), *and* it can be used in a constructor on the same class to initialize the memory during object creation. The last case here is what you run into. Outside the class' constructors' initializers, all access to the field is through the getter and setter, which are instance members. In a constructor initializer list (or in an initializing formal), the object isn't available yet, and you can't call instance methods. And you can't initialize a superclass' private field memory directly, only the class itself can do that.

Apart from conflicting with a superclass' initializer, it can also conflict with an intermediate class' contract.

Consider this example:

  class A {
    int field;
  }
  /// An A where field can only take some values.
  class B extends A { 
    final int minValue = 42; 
    void set field(int x) { validate(x); super.field = x; }
    validate(int x) { if (x < minValue) throw "BADNESS"; };
  }
  class C extends B {
    C(this.field);  // won't work.
  }

Now, if this was to work, and if you do "new C(21)", you are either bypassing B's override of the setter of "field" (which could be really dangerous), or you are using it, which you can't yet because the B part of the object hasn't even been initialized yet so minValue would be null at the time "this.field" is executed (Dart prevents you from ever having this happen).


So, it's for your own protection. :)

/L
-- 
Lasse R.H. Nielsen - l...@google.com  
'Faith without judgement merely degrades the spirit divine'
Google Denmark ApS - Frederiksborggade 20B, 1 sal - 1360 København K - Denmark - CVR nr. 28 86 69 84

Edouard Tavinor

unread,
Feb 1, 2013, 3:00:52 PM2/1/13
to mi...@dartlang.org
Ah, okay. thank-you very much!

Ed
Reply all
Reply to author
Forward
0 new messages