You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 20:09:22