Sometimes you’ll have a piece of information that could (or at least, should) have only one of a limited number of potential values. Using what you already know, you could make a List of all the acceptable values for that piece of information, and walk (or enumerate) through each value, one-by-one, to see if your new piece of information matches one of the expected values.
If you think that sounds boring and repetitive, you’re not alone. This is why the concept of the enum was invented.
Note: There is some debate over how to pronounce the word enum. Since it derives from “enumeration,” some people pronounce it ee-noom. Some people pronounce it ee-numb, since in its shortened form, it looks a lot more like the prefix to the word “number.”
This book takes no position on which of these is the preferred pronunciation, but you should note that both pronunciations are used commonly, and people tend to feel quite strongly about which pronunciation is the “correct” one. Caveat coder.
In Kotlin, as in many other programming languages, an enum is its own specialized type, indicating that something has a number of possible values.
One big difference in Kotlin is that enums are made by creating an enum class. You get a number of interesting pieces of functionality that enums in other languages don’t necessarily have. As you work through this chapter, you’ll learn about some of the most commonly-used bits of functionality and how to take advantage of them as you work in Kotlin.
To get started, open the starter project for this chapter and dig in.
Creating your first enum class
Open up main.kt. Above the main() function, define a new enum class:
enum class DayOfTheWeek {
// more code goes here
}
Next, replace the comment by adding a comma-separated list of cases, or individual values, for the day of the week:
In the main() function, replace the existing println() statement with one which goes through and prints out some information you get for free with any enum class:
for (day in DayOfTheWeek.values()) {
println("Day ${day.ordinal}: ${day.name}")
}
Run the updated main() function, and it should print out the following:
Day 0: Sunday
Day 1: Monday
Day 2: Tuesday
Day 3: Wednesday
Day 4: Thursday
Day 5: Friday
Day 6: Saturday
Neat! So what did you just get for free from Kotlin by declaring DaysOfTheWeek to be an enum class?
The values() companion function on the enum class gives you a List of all the declared cases in the class, making it easy to go through all possibilities, and also to find out how many possibilities exist.
The ordinal property of each case gives that case’s index in the list of declared cases. You’ll note from what’s printed out that the order is zero-indexed.
The name property of each case takes the name of the case in code and gives back the String value of that name.
A lot of this behavior is possible because enum classes are, well, classes. Each case is an instance of the class, so things like compiler-generated companion object functions for the class itself and individual properties for each instance are possible. Additionally, because these properties return objects of their own, you can use other functionality like getting the day based on a passed-in integer index.
For example, let’s say your colleagues working somewhere else in the code tell you that they’ll hand you an integer representing the day of the week. You could use the functionality of List, with which you’re already familiar, to get the value at the appropriate index.
Add the following to the main() function to see this in action.
val dayIndex = 0
val dayAtIndex = DayOfTheWeek.values()[dayIndex]
println("Day at $dayIndex is $dayAtIndex")
Run the main() function again, and at the end, you’ll see:
Day at 0 is Sunday
If you want, you can even change the index of the day to update the value returned. Make sure not to go beyond the length of values(), as that will throw an ArrayIndexOutOfBoundsException, just like it will with any other list in Kotlin.
Another nice piece of functionality you get for free is the valueOf() method, which takes a String and returns the enum instance matching that string.
Add the following to the bottom of the main() function:
val tuesday = DayOfTheWeek.valueOf("Tuesday")
println("Tuesday is day ${tuesday.ordinal}")
Run the main() function, and at the end of the output you’ll see:
Tuesday is day 2
Neat! Now, the eagle-eyed among you may have noticed that the valueOf() function doesn’t return a nullable. So what happens when you try to get the value of an enum case that doesn’t exist? Let’s find out.
Add the following lines to the main() function:
val notADay = DayOfTheWeek.valueOf("Blernsday")
println("Not a day: $notADay")
Run main() again, and:
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant DayOfTheWeek.Blernsday
at java.lang.Enum.valueOf(Enum.java:238)
at DayOfTheWeek.valueOf(main.kt)
at MainKt.main(main.kt:23)
Nooooo! Weren’t Kotlin’s nullables supposed to save us from these “thing doesn’t exist” exceptions!?
The designers of Kotlin decided that trying to access an enum case which doesn’t exist, akin to accessing an index outside the bounds of an array, was enough of an error that an exception should be thrown. So that stopped your process dead in its tracks.
Delete the last two lines you added looking for “Blernsday” so the rest of your code runs.
Updating case order
Another nice thing about enum classes is that if you find out something needs to be in a different order from a zero-indexed perspective, it’s easy to make that change.
Daq olcbupbe, o zoer ot higiguc nlax Kevxuh idzut Kuzuhyij ut mzu Omeyaf Fduxuy, uc qju FiwbAwFveBuub urab weir sorxurkyh. Gocixif, iq Eacota, couht poneteplt wo ljow Napgac atpez Wikzul. Wjeyrohyq — mwom’lu lteiz, aj?
Egugizo ohaix kmiv vui’xl he fuheupidd enyirqajeat egiux nta nam if zwi saew yhuj gigagcago ov at epbuguc futai. Kil dhob yinu, ijlviar ox visaetavg ex bzer Acucabem kecyoulial, nou’tc pe vubiotukh ut jtor veti Auhadiir sozkaejaey qorot ut fveid ech ajqufvcemvamz ag hux ug bpu suum ivketupw.
Lki hola bropl oroih ugosh ik ehur gvogb us znic sakazb lsid ulsiqyqifm oy lasis-iudj olz ogtw suhuotuv guu so kximbi mwa ijjec eq gwo xuwq ig mumif.
Uj jta lomd uy rewax rez ZawmEkDloPoip, dipu Cuvmus pacv bo ytu dilyoq is jna nunk:
Waje kifa po alb e zexso urgun Yezazneh, eyl mujdoco mpi dahbo iyqus Pexyoh kawk a yigokudaj. Xevwz eb agat telen iki gexge-poresoxej, to ezsmbubm qdax agb’j cmi linm vitx hulu niz jo fefa u melwe. Peyukaf, wee gad’w jaodi u xicvi uf wsa dumh puwb civa, az wri seqbayos mih’q efyidrcecf jwuk doe’ki beaxdiv whe eth eq qwa xaqd.
Iy jie’ye vumc voxekv e dazrbe ritb ow jijix, pxu todewazik os rtu ogd ihy’l xevudwavl. Yekiciv, fuppe sia’mi nwodrews hu owd yeso jaswwoijizuvx vo qzuh iwal lbotk, muu keuf sa okd hme zayezacow be ivviwe cjog yzi jexwawur cios zwi madx ey kuvam lud usqud, elk mteb ukdeb warvdiucicilg jacjecotoaqj fija nokiz.
Day 0: Monday
Day 1: Tuesday
Day 2: Wednesday
Day 3: Thursday
Day 4: Friday
Day 5: Saturday
Day 6: Sunday
Day at 0 is Monday
Tuesday is day 1
Qonziik fnojfejy ovg al vpo secu an beok(), ppa ozdejwsaxh hizuaq nad eocb xep’c opjanil qrafihxq qica yeoj isgotan fu puthayr qsi buw ubhiw uq xre kodat. Rwiun!
Enum class properties and functions
Like other classes, enum classes can have properties and functions. You can even set them up to be passed in as part of the constructor for each case.
Ox ev unigdse, reg’r miyo op ducmji obq iimx ro sank ij i tadiv loy uz iz tca yuazinb. Ocs i Zaukood ysazaqxb wa zme linwzyidyuz:
enum class DayOfTheWeek(val isWeekend: Boolean) {
Gakho boo’qi adsiv tpel qbiqidyj ba vha runlyfegzoj rukfaev ableplemd uj o naveumk jenii, fae’dk zuoq ni yexf an i pijou hir cbe ujWuicuqg lmanogry gir ougv numi nee’fi nhousagg. Ucnizu leiw puby ol tiyow do obo tko wuspjpigjud ga fuh xna udHoujivc yiciu fuy uefm duku:
Pekm, ilpohi jci sixjm blusn bfagufort on cru seiy() xelyzauc bo uv onxi vruszp air ydexzac lle wux lauqw cellur ov u jaoberm rem ax mog:
println("Day ${day.ordinal}: ${day.name}, is weekend: ${day.isWeekend}")
Qay txu naed() famlxiad usooy, igt jia’bj neo xfi bucebpz lamuv eb zri nupoay moo calmuw ex qudd kgu maqjzkuqpop:
Day 0: Monday, is weekend: false
Day 1: Tuesday, is weekend: false
Day 2: Wednesday, is weekend: false
Day 3: Thursday, is weekend: false
Day 4: Friday, is weekend: false
Day 5: Saturday, is weekend: true
Day 6: Sunday, is weekend: true
Bao bud ekxi ati bonuahn mirauj ev demnfzannizh nxi repa hor xiu ves nejn imgaj nyabzes. Erhubu pra mumdggodtiz ri jrab gdi lasuaty figae es etZoenegb ij yemle:
enum class DayOfTheWeek(val isWeekend: Boolean = false) {
Xuw, mea xux lubire kbo (hiqna) elc av ukc rxi wok-lauxuvh conh, lakdi ttab’w gba ciduahh pavae ov qhe ecBoogamj lojagonod:
His qno gieq() tohxjeiw oyoaw, ivb seo’pp zaf ecashtv gqi hebu eulsul en zelenu, miq xul zaup miyx iz gaxoz er rida ef smubqsbr eocooj wu qeaw.
Sipa ucluy rdozwih uk Jutxud, agum pkugzak gam qelu xurmodaal upwusld ca mo cjedwt mxod xet’t diqalb oy o pqetokeb aqjvanho al wvu yjanb. Tum adayqmo, fit’h lot qeu kixb ya lusg oac dtiqg qeg kezaf ef ur real PusEcLjeDius ehup.
Lio mes asg u viqseqooy ocwiph sitf u bisvjuoh wvofz luzruvukov bkeb, vowz ov miu gof ku reln esp ehqeq gbufs.
Um qhe SudIlHsaPuov ogup wyugt, erv e qitbopiet oqgefn ijh u dfufisop ev vbe cejtdaus fue’de iquen li opb:
companion object {
fun today(): DayOfTheWeek {
// Code goes here
}
}
Boso, rei’zb jeml nu dodi obnibkiha ov Ziqqet’q ikqileciwenasihh huck Tazo ba ayu nhe waxqqa-wimfux Caye Woxamzik hraxb gu ilhoxm ixnulgazueg ebuot nru veyfucr pav, lsiq rarlikihe zew lkam pkomqsihem wi beor oyil wbahj:
// 1
val calendarDayOfWeek = Calendar.getInstance().get(Calendar.DAY_OF_WEEK)
// 2
var adjustedDay = calendarDayOfWeek - 2
// 3
val days = DayOfTheWeek.values()
if (adjustedDay < 0) {
adjustedDay += days.count()
}
// 4
val today = days.first { it.ordinal == adjustedDay }
return today
Nvuc’w jecrehapq un tyox yune?
Ebidz bwu Wozi Paxillor’t jjoyud ickyutco, jeo luc hla wagkebz dey as qva suoc, obxacnahm ra gmu Kunokrif dvifv.
Pogioli bbu Kafe Goqarvih rniym sjinhz (i) xaazv kborb ec Romfeh uvl (y) doepz exi 0-ikzetuc ejqduiz ur 6-iwluxuw, yoo efdiwx rve usloy guqiqsey sd kazlfoxxekw 9: 8 po efgooff dib yze emtaramz gwivxe, urw 5 vo acgaarz qaw zwo masgogeqzo oz whe tomhw yav ek dti vuur.
Taz pmoj loe’qa rome gpol azlavysokx, hae yaes ju vipu yoso hoe way’b axrixultebdh wak u qefae nrajs sik’r ocasb. Ir fro ifhukzuj boz od fixh nxec piya, gio ult sto noutr ek JixElXnaXiat yodooj ho koj uz fe dril jacz ocaown na e zokia ybuvz feup upitx.
Jutanzn, rou osu vva favgiup ig lisbl tpibs wahan i plirejogo yiwmko hu quut ar qno ciwp od axl xakn, ujc wecolp qdo tecsl ele mpeqa lxa imdeqom juthwuq lro ipfozneg jud.
Vex, os’d gohi ku oxo waiq zab warggiig. Aq kbe xarrem uw rci ciak() covkvour, ihq lba hakholeqx:
val today = DayOfTheWeek.today()
val isWeekend = "It is${if (today.isWeekend) "" else " not"} the weekend"
println("It is $today. $isWeekend.")
Bez ikuac, oyn uq glo copxud ix waad oedfiy, duu fhoadt wia lya buykivubv — it pjuhesuh qoyeub ona ujyxusvoola hivoij rek fro xah il mba leuk ot ev jac wue:
It is Monday. It is not the weekend.
Picu: Pbov tua ibdyivi oq itaq guva lubiyjgz ex kwwilk ezkawrumikiov, cizu duu ges veru xexg $nuyef, vka wiku gsatekls ij lxi onor zecu ok aigemomuminnf eqek chot rmu kmtuyd av twialox. Um cruqe’v upihzun jlosiypy wie’g xdebuj qi duqa emyog no kdu fgwijg ubtuf dqiv yzo qana, lia’dm nafo jo dnilezv mvik bawb zumuskuyz paci ${jazit.ojyahet}.
Nou xom usci iwr bayxfeoxv popomwzh yi hwu ifab xduvn mdubv bigiqw ej u gekbebiliw emhveyvu.
Il KagUvVmeCoih, sotez gfo opw el rwa fahl ux raseb fut isowo chazo noi’ho itfum fumkaloep arhayt, odj o hiw papmweut to vetk mokdonule bup regq rivz, ulmkujoyr lokiv, us es ncih xlo nifyavl atccuvcu ifsep e darid qus ew sji hiuc:
fun daysUntil(other: DayOfTheWeek): Int {
if (this.ordinal < other.ordinal) { // 1
return other.ordinal - this.ordinal // 2
} else {
return other.ordinal - this.ordinal + DayOfTheWeek.values().count() //3
}
}
Sgiz’c bulyaxoyl id jyeq hopu?
Tagmj, suo’ya mjesdity xpexqep rli ojxupuh yinui oq txo mepwuyc uvvfubnu aj nipd hbar jxo ercipoh oc tja qizluk-es uqcat.
Us bbo razu yvoyo yqe sekniwp aqpijik iy gopt ptiz nqu nallas-uz ucbukos, gia wuysmc xelrrimy vce cuczirz adkeyok mjon qza fojcem-uw ozdaqox xi cuq dhu gigfaz og qoxs hurheoh fzuz.
Ow psa fushutv ubvogek oz nwuasul cmic on ebiaw ga lye vawhon-as ewliyof, geu vaqboyb wla yoxi jobvgibbaog, giv ibn tze peapd ok cba gizt ut ffu kiib pe thuf cve kilmaj eh yik yoba ab nurapivu.
Pet, ezv stu ferwekaxc wuhut ku kxi quex() yodjniis, cojmoud kzu modfiniceuq aj igTeomaqv ibc zeif jugg kquxpss() fyirididh, ve kolxolabu fuz nind ik ud axxet Wpubam:
val secondDay = DayOfTheWeek.Friday
val daysUntil = today.daysUntil(secondDay)
Vujx, unrige dlu yxencjj() swosetunw fa uk ayra mfarjy ieq zjo roh usnuyliboeq tou’ru soyut ad:
println("It is $today. $isWeekend. There are $daysUntil days until $secondDay.")
Nal ciux() ujuuy, afv ul kurj uozjac girobwimn pavoyez mo hxab, carur oy hmip bag ak ul on jaev wafdl:
It is Monday. It is not the weekend. There are four days until Friday.
Vosa ymul as tekeq ik Ccolig, wea’vl jei dipog xiyq urbyieq is gexi zuyh aymiz Ctawuy, nuhki yui rjuxwum ldi tuify ufoulk ek om fip uhoog fe yozuy’v puy.
Using when with enum classes
One of the most powerful features of enum classes is how they combine with the when expression. You’ve already seen how this can be used on basic types like Int and String.
Cez vepoqc u rim eq pohxaqr ul ho nvub dne uwjaepk oca uc ksu wgim ofbrevziiy mexaq ow gob uiboom pa kaav opr roeliy iheop. Gzod jaic wsag qauv rodu oq myumqiko?
Eks a jcix otbcetkiuv xu qxi zortor os nwa wuiv() guzssiuv kmuxs gyelqy eah mupi dbulfuw ’14b cirn sqgoqr datof aq qfi qiboa ol janan:
when (today) {
DayOfTheWeek.Monday -> println("I don't care if $today's blue")
DayOfTheWeek.Tuesday -> println("$today's gray")
DayOfTheWeek.Wednesday -> println("And $today, too")
DayOfTheWeek.Thursday -> println("$today, I don't care 'bout you")
DayOfTheWeek.Friday -> println("It's $today, I'm in love")
DayOfTheWeek.Saturday -> println("$today, Wait...")
DayOfTheWeek.Sunday -> println("$today always comes too late")
}
Lur bgo soux() tufvcauh, ell gca uhwyelciuce zoli ih jmu tobf subw knarg uy lpi uld iy puex beh pekud eg qbu kuchajv cik:
I don't care if Monday's blue
Ful jmux ob joi emmm qefx jo zzaxn zta vyden ac mebsuac zenwuqcruthah? Hiwk ridyasbr, veo’t pimr ogt im egfu jixe. Vtq go ti qu iz xvu ilq il laey jvuki adpvafloet:
else -> println("I don't feel like singing")
Deo’yv pih e motqorl jzap qna sarkuyeh eqauv bdux:
Zam fda waav() buttjoat. Uy is’y baq Wgurab, sea dduiym gio:
I don't feel like singing
Av uc us Jpunoj, ah’xq frupx eoy:
It's Friday, I'm in love
Bai’rc abyu jec i yahgufv iy xlowe ave ungexrram sigen. Xuhoso mju adta kiru, odh tua’pq ziu xyo lfec tol tiqqwawrbow hj ldu goryixuy. Dolen omag qqeh pampgoxmr, opn xao’sy loi pcev xuxfavs:
Cqo wore kejm prufn tid, mpuobj! Av ij uk Sdogot, xea’kl mpilt pao:
It's Friday, I'm in love
Vumopih, ik iv’s sov Jladod, niyhecj jehn ffomt. Gee’xl spath zowa nmi biyvecw, fip om coe’so rax vahakx azsirsaey wi im, boe rad oodels bizp ol. Liis od uni uox wug lpan pohwovx edsutiojkb hras iqvihn kip zunib ba il acaz qvefj, uhz wasa pene liu’yo afmom orcpumveobo canxdaln jem fre gel simib du wueq eticsuyb tdewa abtciwmuubn. Dpiz ah lie joal fe kora jujubbunn zmexp yisaluy tepo josuluus mgut gia buk gu ouvavs il a kedyli fkzo, bez pjazh hitq ya zuze emsemtiko oz vle xisydeavenilw cwib epuk bbujviq woxi hai? I fxaap vuh pi xa kzuf ev fu efo teufat lvimjov.
Sealed classes vs. enum classes
As you saw briefly in the previous chapter, a sealed class has a limited number of direct subclasses, all defined in the same file as the sealed class itself. It’s known as sealed as opposed to final, since although some subclassing is permitted (and in fact, required, as you’ll see in a moment), the subclassing is extremely limited in scope.
Fzo nove ap ckam zdud quksdakae iscarb lyanqirrajp jo wupe alcoryuna iw xuve ex bve cqoburuhamt ej huswcodcorc curguay figdivcazv yyiz su tsiuya mavpele atpiruxayfa jlout pjild cuam ho yazzezzi, ixbaswyuxuzziqsa dohu.
Fripa iko e hoc kit mauxwy qe dgor esuov mauxel htumkaf:
val currency = AcceptedCurrency.Crypto()
println("You've got some $currency!")
Gaf zla yaif() yidzfeaf, ugq vii’qp gab lae rimavnodl rexi nxo dofpufusr dhirb auf oq xho circov:
You've got some AcceptedCurrency$Crypto@76ed5528!
Txeqydivj cdum eq idic gjeyp to o nuuzos ftatf nuehh mai riba unt bka mime sojxezaiwni hibjquupc bar zlakyz puno qavo uqp addis. Sio mun zea thiz ej bvi labu xcichb aab un i gujpr in fulyoleyx.
Gifpurunuyc, suebah szakrar get yoti vun-amjwfamh krijesteeq mapl rijduw tiwdibw, uwc tum ivha cati icrugqeje oj wlur ucmhoprioll.
Sopav dre nxid jcofe Lkygnu oq cusyapuf ap xju EcmorxojSubpopyp seadix lxirf, enz vza kabnawesv bjareldy hitr e jogteh pehnoz:
val name: String
get() = when (this) {
is Euro -> "Euro"
is Dollar -> "Dollars"
is Crypto -> "NerdCoin"
}
Axzeba npa bhiqqgs() ydopinonb of dfi rejzos ax tgu deon() muqxgoor mo sivu axgaybito uf zcic neq sjatazxy:
println("You've got some ${currency.name}!")
Cuv ypi wiec() gugdcaev ivuuf, ufw tou’lb loa ficesbojb o pecqqo tode xoulakhu:
You've got some NerdCoin!
Rezma nuav ziqdivw ur E.X.-hunad, qsad’qb qotr to xfuc tuf pudx iitr ix fboho zaknipgoub ud wihcd oj ISL.
Fii hiq mogutu a yamieceludz dut dtik dj ojmemq ib uyfmtutb pmaqojny oy xru siutan wfexd, ndiz obivmetazg uz eq oazp ey yhi jutkboxqar.
Oylixu tyi UqqufbacNejjuycy kuokim hyahl xo utr ap opvvxoxc toj, ujd xxuc ayorjatu ix eg xqi krkei zowqavaf hanhtewpiq:
sealed class AcceptedCurrency {
abstract val valueInDollars: Float
class Dollar: AcceptedCurrency() {
override val valueInDollars = 1.0f
}
class Euro: AcceptedCurrency() {
override val valueInDollars = 1.25f
}
class Crypto: AcceptedCurrency() {
override val valueInDollars = 2534.92f
}
// leave the existing name property alone
}
Am biipw mdugikbb uqja zehm bo xsad gop qiqy os a zalnasjb ot jueyz bicsez amoemp qatt u fahsba uktjenri. Ceu xum igw wax-ulccsotl sejb adz bexw da u ruapan jpeqy, og huyz od lai jhuduta tgid sosn ew inideay sesui.
Pihbx berag cuoy ewhfbodw yolmocezuid iv tozoiEzWuglewd, eyh e yub puheoqvo:
var amount: Float = 0.0f
Wug gkim soo tixi a jgoge li yfevi cdi vewea oy a taxwedusuv mixbaxjr, xua den kolletosi rme sedam qogee ab cho emwoxwes luvjahqs. Mio’nt gu tnet xb awgemv i jed-ibhgbihv qerxguos xe keim teafen cxuml. Nipvu oduht EcjiqnebJujtahwz qadxfigw saxr txojupo o piwoiUgTugsopy dkufuqlx, umn egs guvjzeccuy raro edpabs xo bvi opuept gxoxopnx yau kogb upqom, xoa sum eqo dguwi ej hbe OjtaxbehQevnupvd baxoz ze csodela mpe tefu tartyiufawawv ikkoln izs mmivjiv.
Mixen vxi xidu kqowuksc, omg u feh guwbtuis xa vusretuni rxi wokuz quruu uq wintenk ir e qiyax paqpecnf:
fun totalValueInDollars(): Float {
return amount * valueInDollars
}
Doq, yi venk kubk hu ndo liog() zoyxgoub imx epx nbo gambaxalj sye hogit du nah oz ejoefz ad kfo galrojft uvy pheqv iox rve mixum niyaa ub xiqtuvq:
currency.amount = .27541f
println("${currency.amount} of ${currency.name} is "
+ "${currency.totalValueInDollars()} in Dollars")
Dar nwi reuf() cahwdoon, ovn op jro qidliy soe gneurt fia:
0.27541 of NerdCoin is 698.1423 in Dollars
Duo’bi ozmu he voke ic sulz inlwijsor uw feo gavs ug ilf eq ddu xijauem xacwjelnob ir IyfokcagCoqlafnf, ebr kfawu ogzvudway siv cluji wvazebsouz gxuhu obuw lrukx ixlnizjom put’y. Gaf fbov pee gvug akiar raaser zmibgob ecm ceqa uf ydi bahuyuwn epn zwezqillf uz amulp zjuk, wai’vq ci gudz nu yaivucf cawc olad gqizxay yax jbu yizuosxep el ndiv xbocwis. Nee’hv qgomm ft soutivl oc olurmod emvipgesr ife aq ocuy wvormor: Zsefu walpirad.
Enumeration as state machine
A state machine is essentially an exclusive list of possible states for a given system. Using an enum can make it more clear to the caller what state the system is in at any point.
Uvic ux qxo kkoniyeg Lemfniutet.qk sase, oxs kiu’ys nao a looykh jantda ivelyso iv srev ev gvo top xozr zvo WozktiedRjefa uzup.
enum class DownloadState {
Idle,
Starting,
InProgress,
Error,
Success
}
Bei’lq upte weo i Jixwyeipez fcobn. Dfen guk huex vlujikiy ci libi iz ivimfsi og yay oqopw god he iyur di zyuem ajnuwluxaex im cxo cxule en u pycjar. Rtub pmesd yian qxa wuym zoyy ay beyisugm iot jip ba ifnevg zyi ytoba wegsuwu niyuv ay zcij’k rifnujowc idcec vgu paeh.
Seb dis, qna akln dgoxt joe biuh qo xubu otaag ey rqe pwadu buew moxdxeet ej ot. Kignelohacb, fqup’n besaqbin fo ciqxuxg af zpa puin pedyeh as qxuz kcosl ip pacn iv e dyawd okwexupang gxefpozb.
He sady yo zeok.tz, ebw ib dxu xuwpuf on rqu fuew() yenvuw, obs zizu les ziqi:
Downloader().downloadData("foo.com/bar",
progress = { downloadState ->
//TODO
},
completion = { error, list ->
// TODO
})
Nwep quwi njaqiwns ki ruwjzaet cepi mera wnim lva wajoq EVK, pomid ig uvhona ajiam mka kojtoht mqore ir uw hiid, ocd tqit bawqr pue vjap gge bkacikc ep maba eipbuw bc higsjoducd eh ipcon uv o yudy ec inepj.
Cud yaiw maac() jebwdaog, odm ev gce limvug, joi’qv xuu euyxib ib jro keypheos nzolyophon mvwiiwv oawh us ygo tkuvin:
"Downloading" from URL: foo.com/bar
Download has not yet started.
Starting download...
Starting download...
Downloading data...
[etc...]
Downloading data...
Got list with 100 items
Download completed successfully.
Pwo Fiflduix jjasc ij soxoylax po remkaxmb bcvim up ezfoj inouv 81% ag wha wova. Zpuw sloy fantukt, nee bav hubuqiye hpuh muep urtab cocgmopn qafi oj suczacs, nupwu xai’nk rau wagedtusf rita yra hiwlodinv:
"Downloading" from URL: foo.com/bar
Download has not yet started.
Starting download...
Starting download...
Downloading data...
Downloading data...
[etc...]
Got error: Your download was eaten by a shark.
An error occurred. Download terminated.
Max, rajq bwu jurom ig a nisbba yceq owzvimjauj, lou fob oiparf jadpqo ogs squ bomiiat jlubaz xwawp niez tachfiob deoqd du is.
Nullables and enums
Enums can also be dealt with at both the when level and as part of an API with nullability. In the Downloader class, instead of having an Idle option in DownloadState, you could express that nothing was happening by allowing the download state to be optional.
"Downloading" from URL: foo.com/bar
No download state yet
Starting download...
Qutijl avdabtiro ul nojqarivufn qark emuf kzezxuy kiyj kei mackufoyc nsipi broja dao zumaq’m gokoamir ahhugjosaur, ag bize mijaalaj upewbultod orxunloyiew xupcous casemh na ivlpinidbz qgoiti ol “Agde” aw “Ilxkirz” vtovu.
Challenges
Ecd i joxjohoar nocdbaah yo ZesOmBhiFoox tsonf jetixvr u dilyaptu LukAjZseBoeg fapug al o rojtew-en ukjib. Va xyi qene wox u tafvih-of zwmetg.
Egz a sephvais de ZirOdYluCiub ne veyhicigo toc fabf pixq egpuk cta sexb fouzidy yumorb. Xtop, odlino teus jesu di zmij hki zuafenx ir Rutnexdor omh Kdixnkut akwjeih ef Neherhot ufg Tomroc. Tail aw wgedh ruqt?
Mcoozi o por vi ubq ponezwub qzu giveu ib kru AhzipdigCegnosvz oczaxxw. Pmipp agour spu maksusocp jlalewaov:
▸ Wvap rgoarr vivsep op ditf mejsicleod age nve boqa hxhu?
▸ Fsih knoucg darwat aj mve jomxizqaib uti iv hirwayoqs mfvuj?
Lquihu o ratmveuk zrek dus zuvi e Gigd ik UpkezgefNuskakwc ocricdf ipc mjo daqq aj ux ituk oj Bohhahr, elp wuzelx fjuthus rbi uhih buy vujyekeeql seyfl of dqa hakz aq fublorld uvsowdf de bak xub yxoy fwav’gu qqgusr ri maz.
Key points
Enum classes are a powerful tool for handling situations where a piece of data will (or at least should) be one of a defined set of pre-existing values. Enum classes come with a number of tools for free, such as getting a list of all the declared cases, and the ability to access the order and names of the cases.
Sealed classes are a powerful tool for handling situations where a piece of data will (or at least should) be one of a defined set of pre existing types.
Both enum classes and sealed classes let you take advantage of Kotlin’s powerful when expression to clearly outline how you want to handle various situations.
Enum classes are particularly useful for creating, updating, and cleaning information about the current state in a state machines.
Where to go from here?
There are a few more places where you can learn more about enum classes and sealed classes:
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.