【问题标题】:Dart class constructor initialise fields in constructor bodyDart 类构造函数初始化构造函数体中的字段
【发布时间】:2021-04-27 15:35:07
【问题描述】:

我正在尝试在以下代码中初始化现场任务,但出现错误:Non-nullable instance field 'tasks' must be initialized.。我可以使用 Example(this.tasks) {}Example(String json) : this.tasks = [json] 之类的语法成功初始化字段,但是当我需要使用多行来计算下面代码中的值时,我不确定如何初始化字段。

import 'dart:convert';

class Example {
  List<String> tasks;
  Example(String json) {
    List<String> data = jsonDecode(json);
    this.tasks = data;
  }
}

【问题讨论】:

    标签: class dart constructor


    【解决方案1】:

    在此示例中,您不需要多行来计算值。你可以这样做:

    Example(String json) : this.tasks = jsonDecode(json);
    

    在您确实需要多个语句的更一般情况下,如果字段初始化值不相关,我会为每个语句使用辅助函数:

    Example(String json) : this.tasks = _computeTasks(json);
    static List<String> _computeTasks(String json) {
      List<String> result;
      // compute compute compute
      return result;
    }
    

    如果您有多个字段需要使用来自同一计算的值进行初始化,我会首先尝试将其设为工厂构造函数:

      final Something somethingElse;
      Example._(this.tasks, this.somethingElse);
      factory Example(String json) {
        List<String> tasks;
        Something somethingElse;
        // compute compute compute
        return Example._(tasks, somethingElse);
      }
    

    如果构造函数需要是生成的,并且你需要在同一个计算中计算多个值,并且不改变这一点非常重要,那么我会可能会创建一个包含这些值的中间对象:

      Example(String json) : this._(_computeValues(json));
      Example._(_Intermediate values) 
          : tasks = values.tasks, somethingElse = values.somethingElse;
      static _Intermediate _computeValues(String json) {
        List<String> tasks;
        Something somethingElse;
        // compute compute compute
        return _Intermediate(tasks, somethingElse);
      }
      ...
    }
    
    // Helper class.
    class _Intermediate {
      final List<String> tasks;
      final Something somethingElse;
      _Intermediate(this.tasks, this.somethingElse);
    }
    

    如果类型相同,您也许可以使用List 代替中间值的辅助类。或者,您也许可以重用像

    这样的类
    class Pair<S, T> { 
      final S first; 
      final T second; 
      Pair(this.first, this.second);
    }
    

    你怎么做并不是很重要,用户永远看不到中间值。

    【讨论】:

      【解决方案2】:

      您是正确的,不可为空的值必须在对象构造时作为参数或在初始化器列表中首先初始化。

      但是,您不能在初始化完成之前调用对象上的方法。 (而且你可能不应该反正对象构造应该保持尽可能轻量级)

      如果在构造对象之前(或之后)有任何处理需要完成,可以使用factory 构造函数。实际上,您似乎正在尝试从 json 创建一个对象,这正是 official docs 中所示例的。

      为了简化我链接到的示例并删除有关缓存的任何内容,它看起来像这样:

      class Logger {
        String name;
        bool mute = false;
      
        factory Logger.fromJson(Map<String, Object> json) {
          return Logger._internal(json['name'].toString());
        }
      
        Logger._internal(this.name);
      
      }
      

      【讨论】:

        【解决方案3】:

        Irn 的解决方案很好。你也可以让tasks 可以为空,如果你同意的话:

          List<String>? tasks;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-04-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-17
          • 2019-01-21
          • 2013-12-30
          相关资源
          最近更新 更多