Magnus
Magnus

Reputation: 18810

Is it possible to use this.fieldname in a constructor to initialize a field in a base class?

The following code isn't valid, because this.base1 cannot be initialized from the constructor of a class that extends BaseClass:

abstract class BaseClass{
  String base1;
}

class MyClass extends BaseClass{
  int i1;
  MyClass(this.base1, this.i1);
}

One must do either

abstract class BaseClass{
  String base1;
  BaseClass(this.base1);
}

class MyClass extends BaseClass{
  int i1;  
  MyClass(String base1, this.i1) : super(base1);
}

or

abstract class BaseClass{
  String base1;
}

class MyClass extends BaseClass{
  int i1;  
  MyClass(String base1, this.i1){
    this.base1 = base1; 
  }
}

Using a mixin instead of an abstract base class won't let me do this either. However, I found that there is one way - by redeclaring the field in the implementing class:

abstract class BaseClass{
  String base1;
}

class MyClass extends BaseClass{
  String base1;
  int i1;  
  MyClass(this.base1, this.i1);
}

Is this standard practice, or are there any pitfalls one should be aware of when doing this?

Upvotes: 1

Views: 63

Answers (2)

jamesdlin
jamesdlin

Reputation: 90184

I think redeclaring is fairly common, although you should enable the annotate_overrides analysis option and use @override so that the analyzer can detect if the name in the base class changes.

Note that redeclaring creates a new variable that overrides corresponding getter and setter in the base class. If you like, you also could just declare a getter and setter in the abstract base class and rely on implementations to provide the data member.

Upvotes: 1

Stephen
Stephen

Reputation: 4249

You are not redeclaring the parent variable in the child MyClass, you are creating a new one. They have the same name, but there are now two separate variables.

abstract class BaseClass{
  String base1;
}

class MyClass extends BaseClass{
  String base1;
  MyClass(this.base1){
    super.base1 = "A";
  }
  
  void foo(){
    print(base1 + " | " + super.base1);
  }
}


main(){
  (MyClass("B")).foo();
}

Result:

B | A

Aside from that, if it were possible, it would be rather fragile to any changes to either class.

For now I would stick with your first given example. If you are really concerned about the boilerplate constructor, I am not following it closely but some work is being done on default constructors in dart to potentially allow for the elimination of constructors which could be easily inferred from a simple class like that. You could search for the github issue if you are interested.

Upvotes: 1

Related Questions