最小可复制代码:
enum Foo {
a,
b;
String get name {
switch (this) {
case Foo.a: return 'A';
case Foo.b: return 'B';
}
}
}
void main() {
printEnum<Foo>(Foo.values);
}
void printEnum<T extends Enum>(List<T> list) {
for (var e in list) {
print(e.name);
}
}
for
循环打印
a
b
但是我想让它打印
A
B
那么,我如何重写枚举中的name
属性?
注意:
使用(e as Foo).name
将解决这个问题,但是我在我的项目中有很多枚举,所以我不能像这样转换它们。
另外,请不要张贴答案,如使用toUpperCase()
等,因为我只是提供了一个简单的例子,但在现实世界中,事情是完全不同的。
不能在Enum
上覆盖name
getter "因为它是扩展getter,而不是实例getter。覆盖,又名。实例成员的延迟绑定只适用于实际的(虚拟的)实例成员。
扩展成员是静态解析的,所以.name
的调用要么命中扩展成员,要么不命中,它完全依赖接收者的静态类型。如果你有一个Enum e; ... e.name ...
,那么它将调用扩展成员,这是绝对没有办法改变的,或者改变它的功能。
如果你想有一个自定义和可重写的name
getter,我会引入一个像
abstract class NamedEnum implements Enum {
String get name;
}
,然后让所有枚举实现NamedEnum
。然后,您可以对任何枚举执行(enumValue as NamedEnum).name
。它不会与其他enum
类型的扩展name
getter交互。
将e
转换为dynamic
工作,只要您确保正在打印的enum上存在name
属性。例:
void printEnum<T extends Enum>(List<T> list) {
for (var e in list) {
print((e as dynamic).name);
}
}
只需在枚举中覆盖toString()
,并调用例如Foo.a.toString()
以获得枚举值的文本表示'A'
:
enum Foo {
a('A'),
b('B');
final String _text;
const Foo(this._text);
@override
String toString() => _text;
}