Dart继承Path类遇no_generative_constructors_in_superclass错误求解决
问题描述
核心错误提示
error: The class 'PathWithActionHistory' can't extend 'Path' because 'Path' only has factory constructors (no generative constructors), and 'PathWithActionHistory' has at least one generative constructor. (no_generative_constructors_in_superclass at [paintroid] lib\core\path_with_action_history.dart:3)
代码片段
import 'dart:ui'; class PathWithActionHistory extends Path { final actions = <PathAction>[]; @override void moveTo(double x, double y) { actions.add(MoveToAction(x, y)); super.moveTo(x, y); } @override void lineTo(double x, double y) { actions.add(LineToAction(x, y)); super.lineTo(x, y); } @override void close() { actions.add(const CloseAction()); super.close(); } }
附加错误
- 缺少
Path.addArc、Path.addOval、Path.addPath、Path.addPolygon等22余个方法的具体实现。 - 父类中
moveTo方法始终为抽象方法。 - 父类中
lineTo方法始终为抽象方法。 - 父类中
close方法始终为抽象方法。
Flutter诊断信息
Doctor summary (to see all details, run flutter doctor -v): [√] Flutter (Channel stable, 3.13.4, on Microsoft Windows [Version 10.0.22621.2792], locale en-IN) [√] Windows Version (Installed version of Windows is version 10 or higher) [√] Android toolchain - develop for Android devices (Android SDK version 34.0.0) [√] Chrome - develop for the web [X] Visual Studio - develop Windows apps X Visual Studio not installed; this is necessary to develop Windows apps. Download at https://visualstudio.microsoft.com/downloads/. Please install the "Desktop development with C++" workload, including all of its default components [√] Android Studio (version 2022.1) [√] Android Studio (version 2023.1) [√] VS Code (version 1.85.0) [√] Connected device (3 available) [√] Network resources ! Doctor found issues in 1 category
解决方案
核心问题原因
dart:ui中的Path类仅提供工厂构造函数,没有生成式构造函数,Dart不允许子类继承仅含工厂构造的父类且自身拥有生成式构造(你的代码中默认的无参构造就是生成式构造)。此外,Path的方法底层由平台实现,在Dart层无法直接重写所有抽象方法,这也是附加错误的根源。
正确实现方式:使用组合而非继承
放弃继承Path,改为在PathWithActionHistory内部持有一个Path实例,封装所有需要调用的Path方法,同时在封装的方法中记录操作历史。示例代码如下:
import 'dart:ui'; class PathWithActionHistory { final Path _internalPath = Path(); final actions = <PathAction>[]; // 封装moveTo方法 void moveTo(double x, double y) { actions.add(MoveToAction(x, y)); _internalPath.moveTo(x, y); } // 封装lineTo方法 void lineTo(double x, double y) { actions.add(LineToAction(x, y)); _internalPath.lineTo(x, y); } // 封装close方法 void close() { actions.add(const CloseAction()); _internalPath.close(); } // 根据需求封装其他需要的Path方法,比如addArc void addArc(Rect oval, double startAngle, double sweepAngle) { actions.add(AddArcAction(oval, startAngle, sweepAngle)); _internalPath.addArc(oval, startAngle, sweepAngle); } // 如果需要将内部Path暴露给外部使用,可提供getter Path get path => _internalPath; } // 假设你的PathAction及子类定义如下(示例) abstract class PathAction {} class MoveToAction extends PathAction { final double x, y; MoveToAction(this.x, this.y); } class LineToAction extends PathAction { final double x, y; LineToAction(this.x, this.y); } class CloseAction extends PathAction { const CloseAction(); } class AddArcAction extends PathAction { final Rect oval; final double startAngle, sweepAngle; AddArcAction(this.oval, this.startAngle, this.sweepAngle); }
说明
- 这种方式完全避开了继承
Path带来的构造函数限制,同时可以按需封装Path的方法,不需要实现所有22个方法(只封装你业务中用到的即可)。 - 通过
pathgetter可以将内部的Path实例传递给需要Path参数的Flutter API(比如Canvas.drawPath)。 - 所有操作历史都会被记录在
actions列表中,满足你的业务需求。
内容的提问来源于stack exchange,提问作者S I D D H A R D H A
相关产品推荐
相关产品推荐

