如何从抽象SolidShapeBorder继承,让copyWith/scale返回子类实例?
解决方案:无需重复代码实现子类的copyWith和scale
可以实现让子类(如StarBorder)的copyWith和scale返回自身实例,且无需在每个子类中重复编写逻辑。核心思路是在抽象类中定义一个抽象方法,让子类负责返回自身实例,父类复用通用的复制和缩放逻辑。
步骤1:修改抽象类SolidShapeBorder
添加一个抽象方法createInstance,让子类实现该方法来返回自身的实例。然后在copyWith和scale中调用这个方法:
abstract class SolidShapeBorder extends OutlinedBorder { const SolidShapeBorder({BorderSide side = BorderSide.none}) : super(side: side); /// 由子类实现,返回当前类型的实例 SolidShapeBorder createInstance({required BorderSide side}); /// The aspect ratio of the shape double get aspectRatio; /// The width of the shape given a certain [height] double width(double height) => height / aspectRatio; Path _path(Rect size); @override OutlinedBorder copyWith({BorderSide? side}) { return createInstance(side: side ?? this.side); } @override EdgeInsetsGeometry get dimensions => EdgeInsets.all(side.width); @override Path getInnerPath(Rect rect, {TextDirection? textDirection}) { return _path(rect.deflate(side.width)); } @override Path getOuterPath(Rect rect, {TextDirection? textDirection}) { return _path(rect); } @override void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) { switch (side.style) { case BorderStyle.none: break; case BorderStyle.solid: final adjustedRect = rect.deflate(side.width / 2); canvas.drawPath( _path(adjustedRect), Paint() ..style = PaintingStyle.stroke ..color = side.color ..strokeWidth = side.width); } } @override ShapeBorder scale(double t) => createInstance(side: side.scale(t)); }
步骤2:实现子类StarBorder
在子类中实现createInstance方法,返回StarBorder的实例即可,无需重写copyWith和scale:
class StarBorder extends SolidShapeBorder { const StarBorder({BorderSide side = BorderSide.none}) : super(side: side); @override double get aspectRatio => 1.0; // 根据实际星星形状调整比例 @override Path _path(Rect size) { // 这里实现星星的路径绘制逻辑 final path = Path(); // 示例:简单的五角星路径(仅作演示) final center = size.center; final radius = size.shortestSide / 2; for (int i = 0; i < 5; i++) { double angle = (i * 144 * pi / 180) - pi / 2; double x = center.dx + radius * cos(angle); double y = center.dy + radius * sin(angle); if (i == 0) { path.moveTo(x, y); } else { path.lineTo(x, y); } } path.close(); return path; } @override SolidShapeBorder createInstance({required BorderSide side}) { return StarBorder(side: side); } }
原理说明
抽象类SolidShapeBorder通过createInstance将实例化的逻辑委托给子类,自身只负责处理copyWith和scale的通用逻辑(替换BorderSide)。这样无论新增多少个子类,都只需要实现createInstance、aspectRatio和_path,无需重复编写复制和缩放的代码。
另外,修复了原paint方法中的硬编码问题:使用side.color和side.width替代固定值,同时调整了绘制的rect范围,避免边框超出形状区域。
内容的提问来源于stack exchange,提问作者UnicornsOnLSD
相关产品推荐
相关产品推荐

