Dart:为何无法在初始化列表中初始化函数类型字段?
为什么Dart中这个次级构造函数的初始化方式无法编译?
我定义了一个类,主构造函数接受Function0<Future<String>>类型参数,想通过次级构造函数传入静态字符串初始化,但代码无法编译:
import 'package:dartz/dartz.dart'; class UpdateCheckNotWorking { final Function0<Future<String>> versionProvider; UpdateCheckNotWorking(this.versionProvider); UpdateCheckNotWorking.withStaticVersion(String version) : versionProvider = () => Future.value(version); }
编译时报两个错误:
- 实例字段
versionProvider的初始化器不是常量表达式 - 无法将
Future<String> Function()类型值分配给Function0<Future<String>>类型变量
改用late final并在构造函数体内初始化就能正常运行:
class UpdateCheckOk { late final Function0<Future<String>> versionProvider; UpdateCheckOk(this.versionProvider); UpdateCheckOk.withStaticVersion(String version) { versionProvider = () => Future.value(version); } }
想知道第一种写法失效的原因是什么?
错误原因解析
1. 初始化器列表不支持捕获构造参数的闭包
Dart对构造函数初始化器列表的表达式有严格限制:必须是常量表达式,或者是不依赖构造函数参数的表达式。你的次级构造函数里,闭包() => Future.value(version)捕获了构造参数version,属于依赖外部变量的非常量表达式,违反了初始化器列表的规则,因此触发第一个错误。
而用late final时,字段赋值是在构造函数体内部完成的,此时构造参数已经完全可用,闭包捕获参数的操作是合法的,不会触发这个限制。
2. 原生函数类型与Function0无自动隐式转换
Function0是dartz库定义的函数抽象类型,Dart不会自动把原生的Future<String> Function()闭包隐式转换成Function0<Future<String>>类型。
在初始化器列表中,赋值操作会做严格的类型校验,没有隐式转换的余地;但在构造函数体内部赋值时,编译器会自动处理类型兼容转换,因此不会触发类型不匹配的错误。如果硬要在初始化器列表中解决类型问题,可以显式把闭包包装成Function0实例:
UpdateCheckNotWorking.withStaticVersion(String version) : versionProvider = Function0(() => Future.value(version));
但这依然解决不了第一个“非初始化器常量表达式”的问题,所以还是late final的方案可行。
内容的提问来源于stack exchange,提问作者nicopico
相关产品推荐
相关产品推荐

