如何覆盖枚举的"name"属性?



最小可复制代码:

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上覆盖namegetter "因为它是扩展getter,而不是实例getter。覆盖,又名。实例成员的延迟绑定只适用于实际的(虚拟的)实例成员。

扩展成员是静态解析的,所以.name的调用要么命中扩展成员,要么不命中,它完全依赖接收者的静态类型。如果你有一个Enum e; ... e.name ...,那么它将调用扩展成员,这是绝对没有办法改变的,或者改变它的功能。

如果你想有一个自定义和可重写的namegetter,我会引入一个像

这样的接口
abstract class NamedEnum implements Enum {
String get name;
}

,然后让所有枚举实现NamedEnum。然后,您可以对任何枚举执行(enumValue as NamedEnum).name。它不会与其他enum类型的扩展namegetter交互。

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;
}

最新更新