简体   繁体   English

Dart class 构造函数初始化构造函数主体中的字段

[英]Dart class constructor initialise fields in constructor body

I am trying to initialise the field tasks in the below code but I am getting the error: Non-nullable instance field 'tasks' must be initialized.我正在尝试在以下代码中初始化字段任务,但出现错误: Non-nullable instance field 'tasks' must be initialized. . . I can successfully initialise fields using syntax like Example(this.tasks) {} or Example(String json): this.tasks = [json] but I am unsure how to initialise a field when I need to use multiple lines to calculate the value like in the below code.我可以使用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;
  }
}

In this example you don't need multiple lines to compute the value.在此示例中,您不需要多行来计算该值。 You can just do:你可以这样做:

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

In the more general case where you do need multiple statements, if the field initialization values are unrelated, I'd use helper functions for each:在您确实需要多个语句的更一般情况下,如果字段初始化值不相关,我会为每个语句使用辅助函数:

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

If you have multiple fields that need to be initialized with values from the same computation, I'd first try to make it a factory constructor:如果您有多个字段需要使用来自同一计算的值进行初始化,我首先尝试将其设为工厂构造函数:

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

If the constructor needs to be generative, and you need to compute multiple values in the same computation, and it's really important to not change this, then I'd probably make an intermediate object holding those values:如果构造函数需要生成,并且您需要在同一计算中计算多个值,并且不更改这一点非常重要,那么我可能会制作一个中间 object 来保存这些值:

  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);
}

If the types are the same, you can perhaps use a List instead of a helper class for the intermediate value.如果类型相同,您也许可以使用List而不是 helper class 作为中间值。 Or, you might be able to reuse a class like或者,您可以重用 class 之类的

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

It's not very important how you do it, the user will never see the intermediate value.你怎么做并不是很重要,用户永远不会看到中间值。

You are correct, non-nullable values must be initialized first upon object construction either as arguments, or in the initializer list.你是正确的,不可为空的值必须首先在 object 构造时初始化为 arguments,或者在初始化列表中。

You cannot however call methods on your object before initialization is complete.但是,在初始化完成之前,您不能在 object 上调用方法。 (And you probably shouldn't anyway as object construction should be kept as lightweight as possible) (你可能不应该反正 object 结构应该保持尽可能轻量级)

If you have any processing that needs to be done before (or after) constructing an object, a factory constructor can be used.如果在构造 object 之前(或之后)有任何处理需要完成,可以使用factory构造函数。 In fact it looks like you are trying to create an object from json which is just what is exemplified in the official docs .实际上,您似乎正在尝试从 json 创建一个 object ,这正是官方文档中所举例说明的。

To simplify that example i have linked to and remove anything about caching, it would look something like this:为了简化该示例,我已链接到并删除有关缓存的任何内容,它看起来像这样:

class Logger {
  String name;
  bool mute = false;

  factory Logger.fromJson(Map<String, Object> json) {
    return Logger._internal(json['name'].toString());
  }

  Logger._internal(this.name);

}

Irn's solution is good. Irn 的解决方案很好。 You could also make tasks nullable, if that's OK with you:如果您同意,您也可以使tasks为空:

  List<String>? tasks;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM