1

我已经以这种方式在 Dart 中创建了我的课程,但我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'.想知道是否有一种方法可以以“Python”风格来完成这种课程的创建,提前谢谢你。

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] : '';
  }
}
4

1 回答 1

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

这声明了几个类型为 的成员String。由于它们被声明为String而不是作为String?,因此这些成员是不可为空的;他们永远不被允许null。(这是 Dart 2.12 中新的 null 安全特性的一部分。)

Dart 分两个阶段初始化对象。当构造函数的主体运行时,Dart 期望所有成员变量都已经初始化。因为您的成员不可为空并且尚未初始化为非空值,所以这是一个错误。错误消息说明了您可以执行的操作:

必须初始化不可为空的实例字段“文本”。尝试添加初始化表达式,或在此构造函数中添加字段初始化程序,或将其标记为“迟到”。

  • 使用初始化表达式。这意味着使用初始化列表

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

    请注意,如果您使用同名的构造参数初始化成员,则可以使用简写:

    Lexer(this._text)
      : _pos = -1,
        _current_char = '' {
      advance();
    }
    
  • 添加字段初始值设定项。这意味着在类声明中内联初始化成员。

    class Lexer {
      String _text = '';
      int _pos = -1,
      String _current_char = '';
    
  • 将您的成员标记为late. 这意味着您承诺变量将在任何尝试使用它们之前被初始化。

    class Lexer {
      late String _text;
      late int _pos,
      late String _current_char;
    
  • 使您的成员可以为空,这允许它们默认为隐式为空:

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

    但是,我不建议这样做,因为这将要求所有访问在使用之前明确检查成员不为空。

您可能还想阅读:Dart 立即分配给变量还是在构造函数中?

于 2021-03-20T21:30:28.713 回答