【问题标题】:Is it possible to use a class method to initialize a final attribute in Dart?是否可以使用类方法来初始化 Dart 中的最终属性?
【发布时间】:2020-03-27 19:15:48
【问题描述】:

假设我有一个类,其中包含在其初始化期间传递的函数:

class Caller {
  final _controller = StreamController<int>();

  Caller(void Function(int) callback) {
      _controller.stream.listen(callback);
  }

  void send(int x) {
    _controller.sink.add(x)
  }
}

是否可以用另一个类方法初始化Caller,同时将其标记为final

class Container {
  final Caller _caller;
  int _val = 0;

  void _doSomething(int x) {
    _val += x;
    _caller.send(_val);
  }

  Container() : _caller = Caller(_doSomething);
}

Dart 抱怨 "Only static members can be accessed in initializers." 我知道在调用构造函数之前您无法访问未初始化的参数,但默认情况下“方法”实际上不是最终的吗?与其他属性不同,它不能动态修改。

那么,除了将_caller 标记为非final 并在构造函数中对其进行初始化之外,还有其他解决方法吗?

【问题讨论】:

    标签: dart


    【解决方案1】:

    没有。

    您目前不能创建两个仅通过 final 字段相互引用的对象,或者将彼此传递给其他对象的构造函数。必须在对对象的任何引用可用之前初始化最终字段,并且无法在另一个对象之前创建两个对象。

    对于这种特殊情况,您可以提供一种在创建Caller 之后 调用listen 方法的方法。您可以在调用listen 之前创建Caller。 (当你不使用listen返回的StreamSubription时,我建议使用forEach而不是listen)。

    在该语言的未来版本(以及不可为空的类型)中,我们打算引入 late 初始化字段。然后就可以写了:

    class Caller {
      final _controller = StreamController<int>();
      Caller(void Function(int) callback) {
        _controller.forEach(callback);
      }
    }
    class Container {
      late final _caller = Caller(this._doSomething);
      Container() {
        _caller;
      }
      void _doSomething(int x) { ... }
    }
    

    这个迟到的_caller 字段将在您第一次阅读时被初始化。它仍然是最终的,您可以通过读取它来强制在构造函数中读取它。这有点骇人听闻,主要是因为虚假的读取初始化。

    【讨论】:

    • 感谢您的详细解释,非常感谢!您使用第二种方法的建议是我已经实施的。它并没有强制要求“控制器应该被监听一次且准确地一次”,这就是为什么我想知道是否没有其他方法。很高兴听到late 关键字的未来。顺便说一下,Dart 是一种经过深思熟虑且令人愉悦的语言。
    【解决方案2】:

    "Only static members can be accessed in initializers." 是关于您作为参数提供给Caller 构造函数的_doSomething 方法。由于_doSomething 方法在构造步骤中不可用(因为该方法是尚未构造的对象的成员),因此您不能在此处使用它。

    【讨论】:

    • 我明白这一点。我正在寻求一种可能的解决方法,允许我将_doSomething 传递给Caller 构造函数并将_caller 保持为final
    • 为什么_caller 是最终的很重要?
    • 它没有那么“重要”,但_callerContainer 的生命周期内几乎没有理由改变,所以我认为这就是final 关键字的用途。跨度>
    猜你喜欢
    • 2022-08-14
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    • 2019-07-12
    • 1970-01-01
    • 2011-07-17
    • 2015-06-03
    • 2015-12-20
    相关资源
    最近更新 更多