在dart中为枚举添加方法或值

Dig*_*ion 26 dart

在java中,当您定义枚举时,您可以执行类似于以下操作的操作.这在Dart有可能吗?

enum blah {
  one(1), two(2);
  final num value;
  blah(this.value);
}
Run Code Online (Sandbox Code Playgroud)

cre*_*not 228

Dart 增强枚举类

从 Dart 2.17 开始,引入了增强型枚举类功能。这样,问题中的示例将如下所示:

enum Foo {
  one(1),
  two(2);

  const Foo(this.value);
  final num value;
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以像这样使用枚举类:

void main() {
  const foo = Foo.one;
  print(foo.value); // 1
}
Run Code Online (Sandbox Code Playgroud)

请注意,您需要更新 SDK 约束,因为该功能需要 Dart 2.17:

environment:
  sdk: '>=2.17.0-0 <3.0.0'
Run Code Online (Sandbox Code Playgroud)

添加成员

使用增强的枚举,您可以将任何成员添加到枚举中,只要构造函数是const.

这也意味着您可以向现有枚举添加 getter 或方法,例如:

enum Cake {
  cherry,
  apple,
  strawberry;

  String get description => '$name cake';
}
Run Code Online (Sandbox Code Playgroud)

泛型

增强的枚举类还使您能够对枚举使用泛型。如果将此与成员结合起来,您可以执行以下操作:

enum Bar<T extends Object> {
  number<int>(42),
  name<String>('creativecreatorormaybenot'),
  baz(true); // Note that type inference also works.

  const Bar(this.value);
  final T value;
}
Run Code Online (Sandbox Code Playgroud)

Mixin 和接口

除了声明成员之外,您还可以混合 mixin 并实现具有增强枚举的接口并覆盖任何缺失的实现。

mixin Foo {
  int get n;
}

abstract class Bar {
  void printNumber();
}

enum Baz with Foo implements Bar {
  one(1),
  two(2);
  
  const Baz(this.n);

  @override
  final int n;

  @override
  void printNumber() => print(n);
}
Run Code Online (Sandbox Code Playgroud)

多个参数

最后请注意,即使我没有在上面的任何示例中使用它,也可以有任意数量的参数(和初始值设定项列表):

enum Foo {
  bar(42, description: 'The answer to life, the universe, and everything.'),
  baz(0, enabled: false, description: 'noop');

  const Foo(
    int number, {
    this.enabled = true,
    required this.description,
  }) : n = number;
  final int n;
  final bool enabled;
  final String description;
}
Run Code Online (Sandbox Code Playgroud)

  • @Suragch 我认为所有这些功能都是为了完整性而添加的,没有更深层次的动机。尽管泛型总是有用例。假设您想向类添加一个方法,该方法根据泛型类型表现不同。 (2认同)

Gün*_*uer 27

Dart枚举仅用于最简单的情况.如果您需要更强大或更灵活的枚举,请使用具有静态const字段的类,如/sf/answers/1109818531/所示

这样你就可以添加你需要的任何东西.

  • 将枚举组合到“开关”中时,如果您未涵盖所有枚举值,则会发出警告。您知道是否可以通过自定义类来实现此行为吗?出于维护目的 (2认同)
  • 自定义类无法实现这一点。另请参阅https://github.com/dart-lang/sdk/issues/34847 (2认同)

vov*_*ost 16

Starting with Dart 2.6 you can define extensions on classes.

enum Cat {
  black,
  white
}

extension CatExtension on Cat {

  String get name {
    switch (this) {
      case Cat.black:
        return 'Mr Black Cat';
      case Cat.white:
        return 'Sir White Cat';
      default:
        return null;
    }
  }

  void talk() {
    print('meow');
  }
}
Run Code Online (Sandbox Code Playgroud)

Example:

Cat cat = Cat.black;
String catName = cat.name;
cat.talk();
Run Code Online (Sandbox Code Playgroud)

Here's one more live example (uses a constant map instead of a switch): https://dartpad.dartlang.org/c4001d907d6a420cafb2bc2c2507f72c


Arg*_*tus 13

不.在Dart中,枚举只能包含枚举项:

enum Color {
  red,
  green,
  blue
}
Run Code Online (Sandbox Code Playgroud)

但是,枚举中的每个项目都自动具有与之关联的索引号:

print(Color.red.index);    // 0
print(Color.green.index);  // 1
Run Code Online (Sandbox Code Playgroud)

您可以通过索引号获取值:

print(Color.values[0] == Color.red);  // True
Run Code Online (Sandbox Code Playgroud)

请参阅:https://www.dartlang.org/guides/language/language-tour#enums


Hem*_*egi 12

我这样做了(受到@vovahost 接受的答案的启发)

enum CodeVerifyFlow {
  SignUp, Recovery, Settings
}

extension CatExtension on CodeVerifyFlow {
  String get name {
    return ["sign_up", "recovery", "settings"][index];
  }
}

// use it like
CodeVerifyFlow.SignUp.name
Run Code Online (Sandbox Code Playgroud)

晚点再谢我!


Ray*_*non 10

它可能不是“ Effective Dart”,我在Helper类中添加了一个静态方法(Dart中没有伴随对象)。

在您的color.dart档案中

enum Color {
  red,
  green,
  blue
}

class ColorHelper{

  static String getValue(Color color){
    switch(color){
      case Color.red: 
        return "Red";
      case Color.green: 
        return "Green";
      case Color.blue: 
        return "Blue";  
      default:
        return "";
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

由于该方法与枚举在同一文件中,因此一次导入就足够了

import 'package:.../color.dart';

...
String colorValue = ColorHelper.getValue(Color.red);
Run Code Online (Sandbox Code Playgroud)


Eri*_*nst 8

Dart 中有一个即将推出的功能,称为增强枚举,它允许使用类中已知的许多功能进行枚举声明。例如:

enum Blah {
  one(1), two(2);
  final num value;
  const Blah(this.value);
}
Run Code Online (Sandbox Code Playgroud)

该功能尚未发布(请注意,有几件事尚未工作),但可以通过传递 来使用适当的新版本工具进行实验--enable-experiment=enhanced-enums

结果是一个具有两个值和 的Blah枚举声明,我们有和。当前的前沿在公共前端处理这个示例(因此并将处理它),但分析器尚未处理它。Blah.oneBlah.twoBlah.one.value == 1Blah.two.value == 2dartdart2js


Edw*_*Liu 7

扩展是好的,但它不能添加静态方法。如果您想做类似 MyType.parse(string) 的操作,请考虑使用具有静态常量字段的类(如 Günter Zöchbauer 之前建议的那样)。

这是一个例子

class PaymentMethod {
  final String string;
  const PaymentMethod._(this.string);

  static const online = PaymentMethod._('online');
  static const transfer = PaymentMethod._('transfer');
  static const cash = PaymentMethod._('cash');

  static const values = [online, transfer, cash];

  static PaymentMethod parse(String value) {
    switch (value) {
      case 'online':
        return PaymentMethod.online;
        break;
      case 'transfer':
        return PaymentMethod.transfer;
        break;
      case 'cash':
        return PaymentMethod.cash;
      default:
        print('got error, invalid payment type $value');
        return null;
    }
  }

  @override
  String toString() {
    return 'PaymentMethod.$string';
  }
}
Run Code Online (Sandbox Code Playgroud)

我发现这比使用辅助函数要方便得多。

final method = PaymentMethod.parse('online');
assert(method == PaymentMethod.online);
Run Code Online (Sandbox Code Playgroud)


Bou*_*egh 5

作为使用扩展的其他建议的改进,您可以在列表或映射中定义分配的值,并且扩展将变得简洁。

enum Numbers {
  one,
  two,
  three,
}

// Numbers.one.value == 1
// Numbers.two.value == 2
// Numbers.three.value == 3
Run Code Online (Sandbox Code Playgroud)

带列表的示例

extension NumbersExtensionList on Numbers {
  static const values = [1, 2, 3];
  int get value => values[this.index];
}
Run Code Online (Sandbox Code Playgroud)

带地图的示例

extension NumbersExtensionMap on Numbers {
  static const valueMap = const {
    Numbers.one: 1,
    Numbers.two: 2,
    Numbers.three: 3,
  };
  int get value => valueMap[this];
}
Run Code Online (Sandbox Code Playgroud)

注意:此方法有一个限制,即您无法Enum 上定义静态工厂方法Numbers.create(1),例如(从 Dart 2.9 开始)。您可以在 上定义此方法NumbersExtension,但需要像这样调用它NumbersExtension.create(1)

  • 我认为这是最好的选择,因为地图可以确保附加值的安全。在带有列表的解决方案中,更改/删除/添加枚举类型和相应的值总是很危险的。 (2认同)