dart 枚举 方法
Luke Urban has written a really good article on ways of serialising enums in Dart, and I urge you to read that before coming back here:
Luke Urban在Dart中写了一篇关于枚举枚举序列化方式的非常好的文章,我敦促您在回到这里之前先阅读以下内容:
This article is sort of a response to that: not because there’s anything wrong there (far from it), but because it made me start to think about the approaches I normally take, and more importantly, why.
本文是对此的一种回应:不是因为那里有什么错误(远不是如此),而是因为它使我开始思考我通常采用的方法,更重要的是为什么。
Dart provides a pretty clean and simple way of serialising enums in the first place, assuming you don’t care whether or not your json is easily human readable: the index of the enum value, and the values of the enum class.
Dart首先提供了一种非常干净,简单的序列化枚举的方法,假设您不在乎json是否易于人类阅读:枚举值的index和枚举类的values 。
When an enum is declared, each value is given an index field:
当声明一个枚举时,每个值都被赋予一个index字段:
enum Colours { red, green, blue }Here red is implicitly assigned the index 0, green the index 1 and blue the index 2.
在这里, red被隐式地指定了索引0 ,绿色被指定了索引1 ,蓝色被指定了索引2 。
Theses indices can be used to reference the value within the values list of the enum itself:
这些索引可用于引用枚举本身的values列表中的values :
print(Colours.values[1]);> Colours.greenAnd so, it’s easy to see how this naively gives us a way to serialise the enum. To use Luke’s car example:
因此,很容易看出这是如何天真地为我们提供了一种序列化枚举的方法。 以Luke的汽车示例为例:
class Car { final int id; final String name; final CarBrand brand; Car({ this.id, this.name, this.brand, }); Car.fromJson(Map<String, dynamic> json) : id = json['id'], name = json['name'], brand = CarBrand.values[json['brand']]; Map<String, dynamic> toJson() => { 'id': this.id, 'name': this.name, 'brand': this.brand.index }; } enum CarBrand { Volvo, Mercedes, BMW, Tesla, Ford, VW, }One downside of this approach is that the resultant json now has an integer in the brand field rather than a string, which is less easy to interpret for any humans reading:
这种方法的一个缺点是,生成的json现在在brand字段中具有一个整数而不是一个字符串,这对于任何阅读人类的人来说都不那么容易理解:
{ id: 1, name: 'Cinquecento', brand: 6}where 6 represents Fiat, but not all that obviously.
其中6代表菲亚特,但显然不是全部。
A greater downside is that, should the order of members of the enum change between serialisation and deserialisation, we’re stuffed: the index no longer refers to the correct value.
更大的缺点是,如果枚举成员的顺序在序列化和反序列化之间更改,我们将被塞满:索引不再引用正确的值。
enum Colours { cyan, magenta, yellow, red, green, blue }print(Colours.values[1]); // was 'Colours.green' before> Colours.magentaSo I often find myself creating what I tend to think of as Decorated Enums.
因此,我经常发现自己正在创建我倾向于认为的装饰枚举。
Sometimes I want to be able to fiddle with the order of values in an enum, and augment (‘decorate’) them with extra functionality. Treat the enum like a class, in fact. And there is, of course, a pretty easy way to do that:
有时,我希望能够弄乱枚举中值的顺序,并使用额外的功能来扩充(“装饰”)它们。 实际上,将枚举像一类一样对待。 当然,有一种非常简单的方法可以做到这一点:
class Colour { // the instance part final String name; Colour._(this.name); String toString() => 'Colour.$name'; int get index => values.indexOf(this); // the class part static Colour red = Colour._('red'); static Colour green = Colour._('green'); static Colour blue = Colour._('blue'); static List<Colour> values = [ red, green, blue ]; static Colour named(String name) => values.firstWhere((colour) => colour.name == name, orElse: () => null); }For me, the downside here is that there’s a fair bit of boiler plate to get it all up and running. (I’ve tried various things: auto-adding an instance to the values list on creation, for example [which fails because of Dart’s lazy object creation]; or using a map of name to object for the values [which I didn’t like because of even more repetition of the name string — YMMV]; and so on).
对我来说,这里的缺点是有很多样板可用于全部启动和运行。 (我已经尝试了各种方法:例如,在创建时将实例自动添加到值列表中,例如[由于Dart懒惰的对象创建而失败);或使用名称到对象的映射来获取值[我没有这样做之所以这样,是因为名称字符串(YMMV]的重复次数更多了,依此类推)。
However, I think it’s worth it, not least because there are advantages in adding functionality to the enum itself. Where something lives in the brand, it should be found in the brand IMHO.
但是,我认为这是值得的,不仅因为在枚举本身中添加功能具有优势。 如果品牌中包含某些内容,则应在品牌恕我直言中找到。
class Car { final int id; final String name; final CarBrand brand; // from Luke Urban's original example bool get isGood => name == 'THE BUG' || brand.isGood; Car({ this.id, this.name, this.brand, }); Car.fromJson(Map<String, dynamic> json) : id = json['id'], name = json['name'], brand = CarBrand.named(json['brand']); Map<String, dynamic> toJson() => { 'id': this.id, 'name': this.name, 'brand': this.brand.name }; } class CarBrand { // the instance part final String name; final bool isGood; CarBrand._(this.name, {this.isGood = false); String toString() => 'CarBrand.$name'; int get index => values.indexOf(this); // the class part static CarBrand volvo = CarBrand._('volvo'); static CarBrand mercedes = CarBrand._('mercedes'); static CarBrand bmw = CarBrand._('bmw'); static CarBrand tesla = CarBrand._('tesla', isGood: true); static CarBrand ford = CarBrand._('ford'); static CarBrand vw = CarBrand._('vw'); static List<CarBrand> values = [ volvo, mercedes, bmw, tesla, ford, vw ]; static CarBrand named(String name) => values.firstWhere((brand) => brand.name == name, orElse: () => null); }And there you have it. No more deserialisation problems if the order of the enum changes, and a bit of extra functionality living where it should in the enum, isGood. The downside of the extra boiler plate is worth living with, IMHO. Again, YMMV.
那里有。 如果枚举的顺序发生变化,则不会再发生反序列化问题,并且在枚举应位于isGood了一些额外的功能。 恕我直言,额外的锅炉板的缺点值得一试。 再次,YMMV。
Thanks for reading. Keep playing with Flutter.
谢谢阅读。 继续玩Flutter。
https://www.twitter.com/FlutterComm
https://www.twitter.com/FlutterComm
翻译自: https://medium.com/flutter-community/decorated-enums-another-way-of-serialising-enums-in-dart-bb1d1a0ceb72
dart 枚举 方法