How do I initialize non-nullable members in a constructor body?

Issue

I’ve created my class in Dart this way, but I’m getting the Non-nullable instance field 'text' must be initialized. Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'. I would like to know if there’s a way to do it in a ‘Python’ style where this kind of class creation is possible, thank you in advance.

class Lexer {
  String _text;
  int _pos;
  String _current_char;

  Lexer(String text) {
    this._text = text;
    this._pos = -1;
    this._current_char = '';
    this.advance();
  }

  void advance() {
    this._pos++;
    this._current_char = this._pos < this._text.length ? this._text[this._pos] : '';
  }
}

Solution

class Lexer {
  String _text;
  int _pos;
  String _current_char;

This declares several members with type String. Since they are declared as String and not as String?, these members are non-nullable; they are not allowed to ever be null. (This is part of the new null-safety feature from Dart 2.12.)

Dart initializes objects in two phases. When the constructor’s body runs, Dart expects all member variables to already be initialized. Because your members are non-nullable and haven’t been initialized to non-null values yet, this is an error. The error message explains what you can do:

Non-nullable instance field ‘text’ must be initialized. Try adding an initializer expression, or add a field initializer in this constructor, or mark it ‘late’.

  • Use initializer expressions. This means using an initializer list:

    Lexer(String text)
      : _text = text,
        _pos = -1,
        _current_char = '' {
      advance();
    }
    

    Note that if you’re initializing members with a construction parameter of the same name, you can use shorthand:

    Lexer(this._text)
      : _pos = -1,
        _current_char = '' {
      advance();
    }
    
  • Adding field initializers. This means initializing members inline in the class declaration.

    class Lexer {
      String _text = '';
      int _pos = -1,
      String _current_char = '';
    
  • Marking your members as late. This means that you promise that the variables will be initialized before anything attempts to use them.

    class Lexer {
      late String _text;
      late int _pos,
      late String _current_char;
    
  • Making your members nullable, which allows them to be implicitly null by default:

    class Lexer {
      String? _text;
      int? _pos,
      String? _current_char;
    

    However, that will require that all accesses explicitly check that the members aren’t null before using them.

You also might want to read: Dart assigning to variable right away or in constructor?

Answered By – jamesdlin

Answer Checked By – Senaida (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.