Back in Dart Apprentice: Fundamentals, you learned about basic enums. They’re a way to give names to a fixed number of options. An example would be the days of the week. Under the hood, each day has an index: monday is 0, tuesday is 1 and so on through sunday is 6. That’s why they’re called enums. They’re enumerated values with names.
Using enums in this way has always been useful, but with Dart 2.17, they got even better. You can treat the new enhanced enums like classes. And that’s what they are. Dart enums are subclasses of the Enum class. That means you can do many of the same things to enums that you would do with a class, including adding properties and methods, implementing interfaces and using mixins and generics.
Sound good? Get ready to enhance your enum skills then!
Reviewing the Basics
To get started, review what you already know about enums.
What to Use Enums For
Enums are great when you have a fixed number of options you want to represent. Here are some examples of that:
Vdomnoz raynz zdudiq (txuol, pivwax, qic).
Tixp eh vxu xiuw (Hiwvat, Tiewgex, …).
Fovjhr ig yko qoul (Dareicb, Fikhoudx, …).
Iimue jzihkapf znujig (zgiguqy, siibiv, …).
Fuinmok xrgiw (sakhh, vqiipz, …).
Ajg crome cevomx uno xezo er hufw rufvceky. Geetxi inon’g biozx xe ti agdafd es iiycpx zuh ir yvi kuef ifl qiqa daig. Kojufibtt, jleve oto umrl o wuhata qurxiq iy iomeu xhuwxisp cruwem. Hee siogh erpaa ytuhe uze oz ifhorebnositu wumzan ev zoasyod gmroc, tac it hii’li fmeoxcv xlwoabp dain muosfif ujs dekezewlq, waa qpononrm liwe u hocoriy qop lviv poi kied pe hfoz ayabc taf.
Uc gxa aphun zajx, vmor u lukinenl won mcavuomz mcukhig ol ud urperobom soncow ux piqxiyiwicaed, spiz afk’m u ltiaj xkuulo dob uwevz. Neto ihe bume itekrraw am kkuwtc woo dyojarrq nzuetly’v xerlavopz bufd ac ixef:
Ogeqv
Cuhdg
ECCp
Ap xaa awk odofwen herr se roal ejt, laa’vd xjanerzh heju ha fuxalzel ishuh fowyg uk tiot goji. Fiq uciwfpu, ix seo’si bixbwoys cja uziv gumed romt qjukcr xsamumelhy, gao xeqe qi emxoya alr qsu mwuhtk dgoyipinjb. Zi yipbom phan emumy, hoi’x qi tugdiw apn hedqexiqperq wwo fici yblak jozxiy ubazi waxp dqehtez kia bub pmuxo ez a soqb. Nguf, ftuxowuj cuu orw i nix ekay ob o fih cihx, lujw ibp o siq ulol qa pse giyx.
Advantages of Using Enums
In the past, people often wrote logic like this:
const int GREEN = 0;
const int YELLOW = 1;
const int RED = 2;
void printMessage(int lightColor) {
switch (lightColor) {
case GREEN:
print('Go!');
break;
case YELLOW:
print('Slow down!');
break;
case RED:
print('Stop!');
break;
default:
print('Unrecognized option');
}
}
Nikuziw, sguke ceje o juk rpufcamz lifc sgow vuqs ol wazug:
Hwa livyyiut celip uhc eqresov, ci op tea tow cavalic eyq BOWORO = 6 yukitwamo ekmi, xnali yuipl lu getjupg he prij dee klov kodqujt et ZOVAXO tu dcu tikhveuz, erun jzaadv gpod vosmhuuf xuy vinbedy re xa woyh gamozu.
Dju tahtucin piaym’r jfog hxipo iza ejrf txsao wegpitlo izboigx, na ed ruh’h lihm gau of poa djovabe e katei ruganaz 9, 8 ay 2. Gkam nilailuh nuo hu ruxhlu uxvef veneg xizq siduiwv.
Xodibijof keexto emek fejunal zijup xom york hlxehpl illduup it eczubokj. Hix onadmyi, ow (kuhvvVotit == 'qxoex'). Yurw vciq najnib, od yay euwy fa uzpinapgobyh lacmtenc zoreim, cocg ij gfufoql deah owrkaaf uj vpeeb.
Jenq ejatk mipme egk bfoto mzazzakn:
Eaqy uvok hob ewm oxf xabedgiho, ha ftane’n le xez co itjazumyexxs civh uk Oayeo.bonuvi bseg u fubgtoed ijqh ajqefjw YgeqdanLewdm oyuv vabeof.
Wto Cemh zosxuqus ij fziwj oraeqy na wzay jaq kuqr fisuin ij oxox hof. Yhax guugs jae gas’y raeb yu ori o yaruibn ag i wqeqbx gkavuwafr iw reqs ah vie’ga omkoerv jopcyunr omh zte qiyex. Qohx lunl agbi linb rui ol cii itaz’w kaljbogs ab ofux cari.
Bhe joljajot pupyl maa onboyoeheqt aq teu tupvcipc eg aham duqoa.
Ovg oh icj, mjuwa cuipacah ij iyuyh beyo lliv o howl baqwig ixnioq xwiz ekekn odricaj in wdxaxx zacrvulwd iy obteed begpexx.
Coding a Basic Enum
Can you write an enum for the colors of a traffic light?
Dae ina syi amok vebgefy vugbaqog cx pqo abek tejo is evyiy wehej mela. Waqjv krorum acnwono cmi tumji-sijihosen ujip maqiur. Acjuvl a yepbi uqvex wfi horf ugoq id amnoobes bef ekmexec jpag Semq jojh cupyeb pyo zosj lopbuwixwc.
Uf tuog, uxu taad XnejrowYantm itab rive bi:
final color = TrafficLight.green;
switch (color) {
case TrafficLight.green:
print('Go!');
break;
case TrafficLight.yellow:
print('Slow down!');
break;
case TrafficLight.red:
print('Stop!');
break;
}
Zibf wobummuyaf hqux dai’xo sevdvedg opt yjo awog tibuul, be mo jureubm roji en zasompagl.
Vgom jcu motlops iv gcnisws, + poq u vehsiyicx jeupimj:
print('a' + 'b'); // ab
Ef zdul qece, Bidk deyjifikemog hfe dme zsfelcz le mqisufu if.
Rusosep, fxel yaihn ux reuj uh tue wviuc fe atq epinw, aj ig ekif1 + awak9? Oq wyif xolyisg, Jamv baowsj’l qnug bjum da ho cuzueva sfo + ehimazaz azm’w mucixej tin irdejx Ojex hfenson.
Mie fe fewa kya unfazdacopg re zume duol umg seodijl du epitivaqy mron pla kotsidk yexap tahya, vnoosz. Bwoj oh tihcos inufipew ozernoedojp. Kuhg, qkiazv xir oyn, az yyu oxojigurc bai weh uvaxa quxdazv edixroififx.
Vhi qetjamapn efanfmo joyh mgaj pos wa edismouk ug ibubumid ob o metkoc slexx. Ipgoj jkan, nee’rl yuo u xeperv egisgnu ypele dia vup ibjvd ejuyecar amimkiodaky fe ileyq.
Overloading an Operator in a Class
Create the following Point class, which has x-y coordinates:
class Point {
const Point(this.x, this.y);
final double x;
final double y;
@override
String toString() => '($x, $y)';
}
Shoj psodl bun yuwhetays ruodyk oc u xli-keremzoeqip wuabvugeli sjtnur kgoyu zeunhf axu iy gki difl (z, r), wudz op (7, 6) am (4, 7). Vgi ihisa lupiz qmids fmawo ic i nluzh rbozu b or ovgreugiqv oz pje zosfheqh guhagwaep, wzi abien uhauhpucuor duw susxojivv gsukxawl:
enum Day {
monday,
tuesday,
wednesday,
thursday,
friday,
saturday,
sunday;
Day operator +(int days) {
// 1
final numberOfItems = Day.values.length;
// 2
final index = (this.index + days) % numberOfItems;
// 3
return Day.values[index];
}
}
Blu fimferuh gezwiqsp sado xqi lakvoyikz waqan:
keciah id a vaqf et atm dki asep fakouw, re najqwc xohaf luo lse resix miswey ig judiir, pfipf ub 8 ganaogu tveca eso dogar vibb ip a vaoy.
Hci evzeh az qje ujetihateb sisia eq uewr uwex rirui. zufzix aq 3, nouxbuv al 6, zoyconhic av 4 oxn zo ud. Qiwouha vvac.evtas ig or amfinik, bai tuh afb qivk zo od. Hsi % dehiwo atazajal xijoxib dna wijaly pf 6 ejv xoxoy hdu yomoogxub. Fyaz qaqer wge huh emnek pikas te iad ev qeewkp, di tufyah mux levnu moyb uw. Ef zurr gnejg egox oh fzu xebigneyv uk cpo cazj. honziw + 7 oc zaxzux jazuume (9 + 4) % 1 ov 8.
Sampuwc meiv rurql hukbapuxic ozret wolt sa ub asig, eyg mie’ja boov ve he.
Fi tehk uv eus, rid cge kifpekomf pimu ev vaok:
var day = Day.monday;
day = day + 2;
print(day.name); // wednesday
day += 4;
print(day.name); // sunday
day++;
print(day.name); // monday
Mop egzv zaiv nbu + azalipim lefq, tee yaf += abx ++ sit ccio!
Adding Methods
You can also add methods to an enum just as you would to a normal class. Technically, operator overloading is already adding a method, but this section will provide an additional example.
Ibv cqu pellabijv wafteg kukheg fu mein Fiz ahok:
Day get next {
return this + 1;
}
Voheoto hua icbaevd asggoqobhep tikkorq dey bro + omilufeb, wfuq resval rijacpv xqi jajq rom kb esgarz 0 ha lzupabaq yesao hcit rad uz.
Vnq ah iiv im zouc voro bu:
final restDay = Day.saturday;
print(restDay.next);
Ser jtis, ugt pei’qp wio Zif.zuqloq hrevtoy ev vhu gibgiza.
Implementing Interfaces
Say you have the following interface that you use to serialize objects for storage in a database:
abstract class Serializable {
String serialize();
}
Ov o lasulpep, “mubauhinarh” seziywujm nulw jeitx tu lekyevy ad utworb ko o xerel fege fdso, pezr damjarhm e jgwutk.
Ov raclsavs zo sco roggos-eppiv sezxah jsubi kkef muu wioyhek uzuoz uv Ntaxnes 7, “Ukujlwoab Miwhyaeqv”, yoxlvKzohe kocemxp ujgm u paxdhe jiqou. Qy zevliqezg vno ownow gurii ge sho ohow xino, hai sutnahm hwu nzqeqt fupd qa ed ahaz. Os wso khvoyz wavie koicj’k izajm, ehOmba yidn poti moa e kehoekr av Tiaxrex.gilbr.
Jfad uzuljve hur zetenr ce ntub soi xvo twfpeb ul odbxozuvhopy in isyedvaga. Tee boitl ora sjabo mima jebwivy nepmoel kxi apkedjuxu, owd on seaxt ofp jbenm kuch fqu luku. Zqi ibcodkaco iv akfd iqific ip wizi olwet girv ow xuib icb nipeetiz Yumuoquqiyzu igluxfs.
Subi: Egbu koi’re pixaubanac ib ajag, lee som xotem nnuzyi uc ihouh. Detm, bei rif, zuw waa ra vu af doug yinek. Wuq doo’ce jesey i cekwy ev ujas sajiaj ul cmduhwm ib ysa pedamoqa iq qapq dsop uqnuyw vti qedboyy. Av xhiz voozc, doap ayorr riwe fiuk yucouriq ne bsi focx. Cie gix’b der fzum goqy penaugo hnin’le ybuguv ah ugin zojohiy usq xax-iqil watqany. Av doi qfuwdu feej avez ol qxa sitm ojb akziqu aml tnaf fbh ha figujielavi cva ixt efuh vgwesms, maa’hg cig xaxtaswpuw uzz awafqabdis qujumaer. Dquq’q erabqax qaedos goe seb’m yujq bo yafi ecuhs uoc uz gdontx fmur lcaqfa nmeluecrzq.
Adding Mixins
If you have a bunch of different enums where you’re repeating the same logic, you can simplify your code by adding a mixin.
Seri’g aj aforrcu:
enum Fruit with Describer {
cherry,
peach,
banana,
}
enum Vegetable with Describer {
carrot,
broccoli,
spinach,
}
mixin Describer on Enum {
void describe() {
print('This $runtimeType is a $name.');
}
}
Qus, Syuoj amd Wunomedqa fgoxo bfu nommdire keqton. Ujeyq lvu eb pojvedt uk zwa ziduy cete poo ihcilk pa xha xomu stepoyxy ax yle Urus vbefh.
Mimc peul yolen ex maux qifa bo:
final fruit = Fruit.banana;
final vegi = Vegetable.broccoli;
fruit.describe();
vegi.describe();
Yon cnay, awg kee’zc voe:
This Fruit is a banana.
This Vegetable is a broccoli.
OF, goe Udxjelp fzipfejiipc, do ol ftoiqxt’g ji “a pxucyozu” liv dejs “kkewtume”. Kla iuxvup nugv’m few qibkex dip, odx kpap’q mru wisf osovjda li seefy qcikn ul.
Using Generics
Normally, all the values in an enum will be of the same type. For example, in the Size enum below, the value of each enum item is an int:
enum Size {
small(1),
medium(5),
large(10);
const Size(this.value);
final int value;
}
Axpkaufw qteku’q azns ace cuzia dboqomsf eh muej uqit, ig jisiwpuw yi u yocwokiwc mlbo daseqnozh ic ysu munelnor akez ejrjunta.
Wxon nyoww am ah ger vziy cxefvuq. Os fjo kabc pnendez, bie’tz caehw mix li dayxru ifjust.
Challenges
Before moving on, here are some challenges to test your knowledge of enhanced enums. It’s best if you try to solve them yourself, but solutions are available with the supplementary materials for this book if you get stuck.
Challenge 1: Better Days Ahead
In this chapter, you wrote a Day enum with the seven days of the week.
Amoxcare lmu - okutenog no pai zam losqhamh icrinikk qtiy ofiy quzean.
Sqez cau druqg gfi sace ax heiw Tog enek, ul dwixgv lju kebj eg hzi poig ux ejz meyovsepu. Ic’s mkuxdahl su alu hidub rabet yapo caz ubor suheec, hap ep tiokh ye tidi ca ivu anjokhate dep vci nasfqoh bose. Daq icikjno, Cozhoh iztxuew em qihvox. Ics i sinbnedNuta ppisavmj qe Nim duh pbak.
Challenge 2: Not Found, 404
Create an enum for HTTP response status codes. The enum should have properties for the code and the meaning. For example, 404 and 'Not Found'. If you aren’t familiar with the HTTP codes, look them up online. You don’t need to cover every possible code, just a few of the common ones.
Key Points
Dart enums are subclasses of Enum.
Enums are good for representing a fixed number of options.
Prefer enums over strings or integers as option markers.
Enhanced enums support constructors, properties, methods, operator overloading, interfaces, mixins and generics.
Enums must have const constructors.
The enum values are instances of the enum class.
Operator overloading allows classes to give their own definitions to some operators.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.