如何解决Dart泛型类型下算术运算符不支持的编译错误?
在Dart中为泛型类型支持基础算术运算符的解决方案
问题重现
源代码
import "dart:math"; abstract class Shape<T> { T getArea(); } class Circle<T> extends Shape<T> { T radius; Circle({required this.radius}); @override T getArea() => radius * radius * pi; } class Square<T> extends Shape<T> { T length; Square({required this.length}); @override T getArea() => length! * length!; } void main() { Circle circle = Circle(radius: 0); print(circle.getArea()); Circle circle2 = Circle(radius: 10); print(circle2.getArea()); Square square = Square(length: 20.0); print(square.getArea()); }
编译器报错
Error: The operator '*' isn't defined for the class 'Object'. - 'Object' is from 'dart:core'. Try correcting the operator to an existing operator, or defining a '*' operator.
解决方案
1. 约束泛型为num类型
Dart中num是int和double的父类,自带算术运算符,直接约束泛型继承自num即可解决问题:
import "dart:math"; abstract class Shape<T extends num> { T getArea(); } class Circle<T extends num> extends Shape<T> { T radius; Circle({required this.radius}); @override T getArea() => (radius * radius * pi) as T; } class Square<T extends num> extends Shape<T> { T length; Square({required this.length}); @override T getArea() => length * length; } void main() { Circle<int> circle = Circle(radius: 0); print(circle.getArea()); // 0 Circle<int> circle2 = Circle(radius: 10); print(circle2.getArea()); // 314(pi与int相乘结果为double,as T会自动取整) Square<double> square = Square(length: 20.0); print(square.getArea()); // 400.0 }
注:radius * radius * pi的结果默认是double,通过as T转换回泛型类型,若需精确控制数值类型可根据场景调整。
2. 定义算术运算抽象接口(支持自定义数值类型)
如果需要支持自定义数值类型(比如自定义Decimal类),可以先定义支持乘法的抽象接口,再约束泛型实现该接口:
import "dart:math"; abstract class Multipliable<T> { T operator *(T other); } abstract class Shape<T extends Multipliable<T>> { T getArea(); } class Circle<T extends Multipliable<T>> extends Shape<T> { T radius; Circle({required this.radius}); @override T getArea() { final squared = radius * radius; return (squared as dynamic) * pi as T; } } // 为int扩展Multipliable接口(int本身已支持*,仅作示例) extension IntMultipliable on int implements Multipliable<int> { @override int operator *(int other) => super * other; } // 为double扩展Multipliable接口 extension DoubleMultipliable on double implements Multipliable<double> { @override double operator *(double other) => super * other; } class Square<T extends Multipliable<T>> extends Shape<T> { T length; Square({required this.length}); @override T getArea() => length * length; } void main() { Circle<int> circle = Circle(radius: 0); print(circle.getArea()); // 0 Circle<double> circle2 = Circle(radius: 10.0); print(circle2.getArea()); // 314.1592653589793 Square<double> square = Square(length: 20.0); print(square.getArea()); // 400.0 }
这种方式灵活性更高,适配自定义数值类型的扩展需求。
3. 使用动态类型(不推荐)
可以通过dynamic绕过编译检查,但会丢失类型安全性,运行时传入不支持*的类型会抛出异常,仅适合临时调试场景:
import "dart:math"; abstract class Shape<T> { T getArea(); } class Circle<T> extends Shape<T> { T radius; Circle({required this.radius}); @override T getArea() => (radius as dynamic) * radius * pi as T; } class Square<T> extends Shape<T> { T length; Square({required this.length}); @override T getArea() => (length as dynamic) * length as T; } void main() { Circle<int> circle = Circle(radius: 0); print(circle.getArea()); // 0 Circle<double> circle2 = Circle(radius: 10.0); print(circle2.getArea()); // 314.1592653589793 Square<double> square = Square(length: 20.0); print(square.getArea()); // 400.0 }
内容的提问来源于stack exchange,提问作者user8234870
相关产品推荐
相关产品推荐

