Dart中如何在子类构造函数中定义值传递给父类构造函数?
Dart构造函数初始化逻辑与可选参数默认值问题
初始需求
现有代码:
class P extends StatelessWidget { final List<int> l; final int x; const P({ required this.l, required this.x, Key? key}) : super(key: key); @override Widget build(BuildContext context) { // TODO: implement build throw UnimplementedError(); } } class A extends P { A({required int x, Key? key}) : super(l: [], x: x, key: key); }
想要把A类的构造函数改成类似以下形式:
A({required int x, Key? key}) { final int a = 3; final int b = 5; final int c = -1; }: super(l: [a, b, c], x: x, key: key);
问Dart中是否可以实现这种需求?
场景更新:复杂参数下的报错
之前的方案在简单场景有效,但遇到复杂场景失效,比如:
class A extends P { A({ required int x, Key? key, ChangeNotifierProvider<UIComponentState> a = ChangeNotifierProvider<UIComponentState>((ref) => UIComponentState()), ChangeNotifierProvider<UIComponentState> b = ChangeNotifierProvider<UIComponentState>((ref) => UIComponentState()), ChangeNotifierProvider<UIComponentState> c = ChangeNotifierProvider<UIComponentState>((ref) => UIComponentState()), }) : super(l: [a, b, c], l2: [a, b, c], x: x, key: key); }
此时报错:
The default value of an optional parameter must be constant.
问该如何解决?
初始需求的实现方式
Dart不允许在构造函数体里写逻辑再调用父类构造(父类构造必须在构造函数体执行前调用),但可以用初始化列表结合表达式实现类似逻辑:
class A extends P { // 直接在super参数里计算列表 A({required int x, Key? key}) : super(l: [3, 5, -1], x: x, key: key); // 如果逻辑更复杂,也可以用立即执行函数表达式 // A({required int x, Key? key}) // : super(l: (() { // final a = 3; // final b = 5; // final c = -1; // return [a, b, c]; // }()), x: x, key: key); }
复杂场景报错的解决方法
报错原因是Dart要求可选参数的默认值必须是编译时常量,而ChangeNotifierProvider((ref) => UIComponentState())不是常量(闭包和非const构造的实例都不能作为常量默认值)。有两种解决思路:
方法1:用可空参数+空值合并运算符
把参数设为可空类型,默认值设为null,然后在初始化列表中用??提供默认实例:
class A extends P { A({ required int x, Key? key, ChangeNotifierProvider<UIComponentState>? a, ChangeNotifierProvider<UIComponentState>? b, ChangeNotifierProvider<UIComponentState>? c, }) : super( l: [ a ?? ChangeNotifierProvider((ref) => UIComponentState()), b ?? ChangeNotifierProvider((ref) => UIComponentState()), c ?? ChangeNotifierProvider((ref) => UIComponentState()), ], l2: [ a ?? ChangeNotifierProvider((ref) => UIComponentState()), b ?? ChangeNotifierProvider((ref) => UIComponentState()), c ?? ChangeNotifierProvider((ref) => UIComponentState()), ], x: x, key: key, ); }
方法2:提取默认创建逻辑为静态方法
如果默认实例的创建逻辑重复,提取成静态方法可以减少冗余:
class A extends P { static ChangeNotifierProvider<UIComponentState> _createDefaultProvider() { return ChangeNotifierProvider((ref) => UIComponentState()); } A({ required int x, Key? key, ChangeNotifierProvider<UIComponentState>? a, ChangeNotifierProvider<UIComponentState>? b, ChangeNotifierProvider<UIComponentState>? c, }) : super( l: [ a ?? _createDefaultProvider(), b ?? _createDefaultProvider(), c ?? _createDefaultProvider(), ], l2: [ a ?? _createDefaultProvider(), b ?? _createDefaultProvider(), c ?? _createDefaultProvider(), ], x: x, key: key, ); }
内容的提问来源于stack exchange,提问作者Randomize
相关产品推荐
相关产品推荐

