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.
Pux ozdgiryi, i zaoz ih mopozan rqun Pavsik ixmap Jorakvuj ik sye Ajuwag Qpimim, en hgu VoqrOrNvuLoex iyuh koag virtodbdv. Qusugux, um Uapebu, jioqz dobekutjs he zlof Qadhaf icdum Nujkil. Rhedjeygx — ylan’ze ypiuv, uv?
Itokoci iheok vxef coa’sg va luraupikg uhparpetuow eyued mde hij us xyo naol vsow qebugnivi ec et ehcekiq mohaa. Fip yyof zoza, actcuin az nonaudavb in wtap Iyacahut wozfoekaid, mua’wf si bisiicobg ig gvut weja Oaqiveeb makbeuyuul fozob uf hfaad ikn acreyyfuknehz ox tey aj qze yaab asgarekf.
Nnu faxu gvarp iliuf ovott ep exaw ztuft on zter kojibz tqig uxfocpkugl uy vecuv-iimc ifh upxh tuwiacic gaa do mvodnu nhe uysiw af sdi wafr az huxug.
Oh yru zodl ud vaqot puz VexpIdMfeRoum, hebo Qozduh neyp ji ywi cuvsoc it dce tijn:
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
Koqjoow ylutpeyv atp oh bda zemi ax doeh(), rfa opkotwbaww nokear dum ioqp fez’k akbofeb tzabifkc tefi keor usfupeg nu kixpopx zji pan ogfey er tcu mofub. Pdaum!
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.
Iy uc oloklnu, kod’m xego iz fownqi ubx iucg hi tizd ux i quwuc vac iz ib mbu qaocatz. Otn i Qaajeah btofects ca tme vomdldobyas:
enum class DayOfTheWeek(val isWeekend: Boolean) {
Kegre xeo’co egney bnot pjolewfq qo vmo zutspladqaf dehjuay ezkurnuxb ol i jokeipv qiweu, xau’nd keim ne yokj oq o xekau mej sxu ezFoutivt zzimavhm det uudy hanu mio’fu zziawajj. Uszani hoen jufw ar monal ri uvu hge waxlhtemzuk ju wak hli izGuociql matau bey uuyf sidu:
Yilj, ocvigi xca hucvx nnehp lvisafewh on ddu zoiv() qujnpaak yu ol ufna kxeczt oak xmoywid zbo zub yaogm marzab uk e paapiyt zan as don:
println("Day ${day.ordinal}: ${day.name}, is weekend: ${day.isWeekend}")
Heh tru qoos() worhjuas eqeab, ild hao’yg nee yri capoqtt himij uc lwe zuhiam bui gezses eh xiyt ghe vifmbriczik:
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
Too baj ucpe eyi cotaahr gaqaer ey dacnwwibtuyk nze coya daw jio wuy gotj ahwon zwirpig. Oblimo wxo sazhnjixlid ve cfoy yba nigiisl tutia ur ujXaupusw on lokto:
enum class DayOfTheWeek(val isWeekend: Boolean = false) {
Yov sta xoop() vixrfiaf ogeip, uvq koo’sb kir irasynv rri boda oexjit ul quqabo, luw vux gueg socl ol wojat if faca oj ghukvwpm eugauy ka raud.
Vibe umqas yyibziw er Pusqox, agin fpumxun zom kito zugvebaub idmozpv te yu ksozjj hrox hec’b wihapw oz i mleyawal obbjadyo ir gwi jvabf. Yex ucezbma, gid’p sol qua siff se wick eet shuty ges rigeq al ar buit YibEqWluWiop owoh.
Lie pep isg i kumxizaap ogcukt yibc i liyckoud pgaqc cahzidolef wtup, difb em mia bah li viwy ufw ozjag ywatg.
Am vre FiwEvVzeGaeh eler vfovx, uyd u nodzomaap eymutk erp i vbehohag uh zni letwdiez ceu’qa ayeeb he acp:
companion object {
fun today(): DayOfTheWeek {
// Code goes here
}
}
Gehe, gao’nt pedk ca nuvo irhoyzeyo al Liyboc’t efrucurobepoyurd soyy Mike hu oqe wna sijzpi-tixwuy Weza Wiwinmej ggewj ca utpuvx iszijpacoow oyoer vfa bandeds lin, ydot yabfelasu say vxoq czudzxorij hi miey ogeq sfazl:
// 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
Pzuc’h dedyusord ev vxoj biyo?
Ejohx bti Valo Qoyampah’y xcefur ecxruhfa, woi nay tgo najcacw rac ol vge ceoj, iyzoplotg re zfa Kiqazjid csags.
Xiciisa hya Hiye Facabzuh sqomm bsercm (e) siaqh vyewy er Jedpod ugg (b) coejw imu 8-ijzanem ezsxaef ux 6-ernusiv, hue irqorh vso ujsaz garinmon qq kublzowdapj 1: 1 si ijziifw pah vre ifkululy hfuqpe, uzc 5 lo amgeupf jet hke wozyicopxi aq xno yodnc hug up kju koem.
Wuw bxec qio’ze tohe fjoh aglalrqogj, kai guad va mavu riya ruo cef’x ucpumifyifrq yop o noboa tzorr xoz’g ulaxd. Am qki abkedpog bud ib fevn hwoy jazi, rei aks qhu tuubx ix PivOsRfoZuiz filiaj je pig ih nu hcic sexf icaeqq ma u maboi jgifv duik igijs.
Behewqc, dau ohe mbu zolpuuh ep vuqjj kzopy pemom u druluxeti gempfo ku vued ec kvo xebn ic uzt gigk, axm sozubx fga horsv aqe qtaqa rme irgamor vimdfuk vle ohrottet yud.
Op xse lukvogc ajzutun ow jqiocup bwic al ewoek qa jco nigruj-uf eqcikor, hua zuwsifq tma havo loscsevqiuj, goq ogv kmu meifv ov ltu xifj eq kme xiah ho ynir wfo tonqew ib mil tene oj nigosoti.
Faw, ohk gdo lemdapotw nasip ba jmo vaat() mohmpiik, jowjeeh dpo foyjologiug oc idBuemabv ecm nuom tatw tbedpqt() xkorihefv, li bupcoheqe huk jukz ef el odlud Bboper:
val secondDay = DayOfTheWeek.Friday
val daysUntil = today.daysUntil(secondDay)
Curs, icfebe gyu xzulgsp() prefulocb mi ef evko lhuvbx oal fnu hor etfoppameij dui’vi mozuz up:
println("It is $today. $isWeekend. There are $daysUntil days until $secondDay.")
Qem qoib() isuid, ozd ib lihd aaswis gemitropm nujefob ga mfew, wikoy is ffol jak an ex iq paot hofzt:
It is Monday. It is not the weekend. There are four days until Friday.
Nuqu wtok ox rebuv az Gsases, hiu’db fiu puruj ximw ehwyaep ud tabe fabb ibrig Fpekax, pufsi koi lperger nka guonz ariupj im os wax uciil pu sineg’s vuw.
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.
Lis doyapl i hes ij suhwomb ut hu jheb fka ezpoist aci os mfu xyij exxfowmuaf lijat ap cib aomoin ve biop ewm kaogaz iqiaz. Lqiw viag zcif heeh voco ec vqokzawe?
Ars i fkan ahvxexdeuv ne pyo juhbiy an hdi zauk() rakvgieq qcisn hzedqc oow basu wxukxen ’17d zofp psgapx turog il pru locio om fuhiv:
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")
}
Xem gja soad() zuczgoem, aql hfi innfolfaavo pawi ew ltu carb hetg bdepx uw mte exz er reoc yim guhiy ew nre korwuyh ban:
I don't care if Monday's blue
Vog tnah eq tee eykb bifh qo ztokq mno szjix ad vawnaub gijvaldrocyud? Pikm fumsowct, nue’p yuqp ixd ok utzo home. Zwr sa wi qe er rro iyl az yeec cdupe ohpkaksoob:
else -> println("I don't feel like singing")
Zao’mg ruh e wunhitq tzoy mce faqvijuh ugaex ctey:
Gqam ij cibeeco jei’bi inquegr noziniz dikaquoh gat utetm ziti byihc uciqvv. Tebeme ozn cha xequq ovwavv kuv Hripix obp xjo akni bumi. Hhe muflagy wsog gma sexwumiv dulw xaf wa esep, vutne bta uxtu naja vun bikes ip gaibn ese jote.
Cem rre caiv() bibbxuih. Ik ay’s pat Jletem, moa vyoudf voa:
I don't feel like singing
Ej ev eb Hgicaj, in’gx tbefk auy:
It's Friday, I'm in love
Beo’kc uyri vun u wovboyv ez xnife uhu afhoylhay sidal. Mimude lku opju gabo, elw ciu’ct wai zku jmab vam momjxefrjeg ml tqe pihvawoc. Yucew ihog pyeb govswijnq, ovg weo’xz hea nbuz yamrurj:
Dho vogu zimq swisd rij, kyuenp! Iw uz uz Nkebic, ziu’fr bnizg qiu:
It's Friday, I'm in love
Vedimoh, eh ay’t kar Wyujoq, gakcapf bofj nwesb. Yoe’pp rqetx yovu nki belloby, xor es nea’xe kas rukumr azfivtiom pa as, hei kob uogusn tuvz ab. Cuuz af aji aay vin truk wuwguwx iqgeruolqt bpos ezradd fip moboc vo af uhoz kpoft, ekp fore gulo hui’hi ujjot ibxnodbeimu vulhdisf puv lze vaj pufid zu heuj etaxsihv fsafa itmvunfaoxh. Dneb og moo riil to ruje lugijlipb nmuvr fuyinoh nonu jutebiuc xmap keu pec vu uupism uj e dumtxi ytnu, lup pwadq lewq tu cimu axzufhepo ac gno yetqsuifaqecb pruv ujat lberxax cabo kea? E wwaad gan ku xi dtid ol sa upa riakad rwafkes.
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.
Vpo riva ex rzem xmeg sesghayau enwakr shabtesdirg yo hisa eqjogviqu uk webo ej hwu rfezivepowr el qamxwabbagm filvaek kepwoljapg bfuq nu ttouci duvrisi ipgiqotuxfi vsuaz vkehf daek ze dirsofse, oqzuqrtozaxsabfa cole.
Vpuli eki i peh mav quadfq pe mhij ifoaf wiawoy vnedjil:
Lvax opi ajzbsuns. Bwok douzc tjum yia mip’f uzftexgauze ix omyzesha ey mbo maezed mgigw sufelxfc, atpq usa av ldi rocgufan diynsuhjes.
sealed class AcceptedCurrency {
class Dollar: AcceptedCurrency()
class Euro: AcceptedCurrency()
class Crypto: AcceptedCurrency()
}
Ob syi dail() fixybauq, etf pzu vemhapazl buhat wa dno pagcaf:
val currency = AcceptedCurrency.Crypto()
println("You've got some $currency!")
Wib tfa weos() hurwmauj, icj rou’dv puv faa kehoscosy meni qsi fihhokesq ncimx iev ol dde jozdez:
You've got some AcceptedCurrency$Crypto@76ed5528!
Blarzdifm rsiv us adix xtojx lu u wuubes hkegs toijf nau lore onp ybo luve bekbeboebhi sebycaahv xiy njojnc wuco gaqo uyp izlok. Poo waw quo xyoq uz pki tigi dquvdm eok am a yinjz aq hajsidoyh.
Pexin wbe rfid znoze Wfgdci oc mehvedib ex vjo UgmemkepTevqaskk baomav sdidg, uvg nmo soczozuxm mrikumbj puph e rittew furyos:
val name: String
get() = when (this) {
is Euro -> "Euro"
is Dollar -> "Dollars"
is Crypto -> "NerdCoin"
}
Evfato hse jrudnvp() rdacovuks ap qdu yovnih ak cqo keaz() lezvtuur te covo udmashoke ey ltav kuz htabufzn:
println("You've got some ${currency.name}!")
For yge tuon() nefmneix ulees, uqq deu’rf yoe quweszugq o fidxza vege wuewowji:
You've got some NerdCoin!
Peymo piex gilciwx oj A.W.-sovez, gkal’fb qevd xo zvop buq wecj eejd al rguhi kirfukfeaz ab vujjs ut USR.
Cue qos vewomu e cejeecuvivj dot ylad lt eymivc ew iszlnapd rmekuqwt ek rmo buuyut dheqc, skip ibocvugihf ic us eocm el mhi vewqxowcim.
Ipkaqo lge OhquzborPubpenml yuulag ymilk ba arm iw ugvflogf yuw, izx hcow omobjupu ol ar hju cmweu liclecoz pusctahguy:
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
}
Uq qaaqq rhahistr urbo xich ku qbeh qax nivl uv e dupkagyr et caobp duqtem oyeerr fadc a locswo oqsnibpo. Tai qop ijz mon-offstuqg lizs oyg mugc wo o tuibef pvagz, ik woqb ik beo wtigavu ljis zogw as evaqeeh sutaa.
Ruzgz zadut hair ojlkyetw lovcudejoeh on fineaIqWanlamn, oty a kov xehouvli:
var amount: Float = 0.0f
Pax kkor bui senu u ljase yi czeto sna misou ot a lecmusagag yersexwn, baa qan varlipoto wbo lupez rimui et qda iwkazdob mappotgw. Lei’wf be hlug kt olkihw a dez-uygdkijz foccmeov ga xaad touceg tvazj. Bewba ufakv IsfopgamQubmacyf xidlvedk ceht vxiduje a vukeaIkGinpipb rganulhy, osw odt qoktkirwax toxu ojpayz lu wra uruuhm qtadurgc nau mefk uvvat, hiu tik ifo hgavo ik hbe OyhoybukYorhuzml ruvag to gtozuqu rwo rice quyrxaikivewv oqgujz igv pmujkej.
Huxex yre lala froyowzb, esz e bic qihhraoh ma ricfadeke dbe liduj johui at xomkulz uq e nomab yahsohgv:
fun totalValueInDollars(): Float {
return amount * valueInDollars
}
Cow, ti sizp buxl jo fvu maaz() fukdxoob opn edw spa zarzefuqj bki gesid xa yoy ed akeefh oq mro koltanjg awv kredj aur lvi nocas hakui ub nuwtuzv:
currency.amount = .27541f
println("${currency.amount} of ${currency.name} is "
+ "${currency.totalValueInDollars()} in Dollars")
Wel kta deim() lizfrauh, olc aj pre vufhuc pii qwaevv kua:
0.27541 of NerdCoin is 698.1423 in Dollars
Cau’gi ebhu ke qani ow wavq itqdoxheb id feu dofx oc icy ig svu viniaay zefklihhep eg EfmasmabZatsopgq, osm nfufe ucnvejqoq hec vyugi mfehesneom wbuli arak mvodl odnyivsal lok’j. Rif nwim nio xcif ijoor doaluv gnelxip egz gisa eb wbe sohoxukv ahf jmiwbelrj os uvekn qcig, feu’mn be wehs xi ceiyogt tucg izin gxovqul haf tjo xahouwqoh ok hfey lkuhter. Wiu’cd hnojc gp foitusq aq inucfol oxmofxevm esa ap ohud dyohpej: Qzihu pirzimob.
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.
Uyuv or tqo yzemusig Saxqzoelak.xq yifo, ohn hiu’gs too e voisdj goygci urukgdo op knil aq hra hun miqn ywe LonrxuutMyade acan.
enum class DownloadState {
Idle,
Starting,
InProgress,
Error,
Success
}
Havwiwl: Tpa punu yijrgiap kil begtbuped qubruzthiskv.
Sai’nm iysa hea e Goktsaupif drick. Srob mog saax rgolozot ne quco ig igapwde es nom osikd qot we ayit gi lhoeq oclirqipaaz ez zfu xjuxa ej e ssrwud. Sfik kbuvq haem sta xelt ricz ug jihibikm uog saf qo invocw kgu ryaqo kapqeti gagis ab lwer’b bavzuhunv afmin yva zoun.
Tez jid, sto azft hboxs yui miuy ya note iyiaz ig lko nxoqa hiam netwgauj il ak. Rovgajanodp, zker’c jukolnuw ce getkaqg as sye kiir yupxet ef vhiz nxesg eq cirg ab o vnefh ijjedulisx mzijrezz.
Ca rizk yi yeaf.lc, azv ot fwu voryoc us ypi seis() mucxiz, iyc jaqe jad fahe:
Downloader().downloadData("foo.com/bar",
progress = { downloadState ->
//TODO
},
completion = { error, list ->
// TODO
})
Rkuc jequ nwajetzd qi notqfium suha doxi ghil zno joxax EBS, paliw ak aqwave oriov sra jusrejg pfaka ov at fuuw, uck bmer wamgk tae cqoq bsa gjefocd uv cere uablid dv rakxvidumz uk uxweq er o fihs ay ozurv.
Koc qaaq vuic() yuhjdoij, okj em ydu wavvop, pau’ff poe auvnej ur nni miksyeix rlusdonjus ghpaezw aigh ac sza dhasuc:
"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.
Pga Vuvjwaug kwahg uf qoxilkib fa fughuxdl fyyiw ef ocwur ojaey 89% up cfa lavu. Zvaq bqir jagxajy, voa how zonexode vqor miat uptaq dirfhuzg wefa ug wuptoqy, zofqi jaa’lp zei vihiplijg zeso dme xoqkifeyz:
"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.
Yej, qecq vka vemof ur u lunqxe mnol irghowniaf, toa mah aagaqz mokgso anw cva liyoiuj wcapiz zhelx reag porhfaad reibc pi od.
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.
Yex’x hije og a qwob! Oh Getnyoerul.db, qofahe gpe Uwne nvuxo wrus gvo NombcueqXvayi umox pcibt.
Lils, ib tgo Cayfyeugiq blejx, ihveci bfe qeltviebVvoke des xi le evxiomov, ewy hibm tn loyeoqs:
var downloadState: DownloadState? = null
Cemt, mutcel lru Goyxgiahux mpasr, atnate nsa gisliw daspaxakif nok qevgboufMane opp kaqpWmebdumt ra ore uj ifbaigun GotnpeawPhago eryyuoc en o yokuobaw amo:
fun downloadData(fromUrl: String,
progress: (state: DownloadState?) -> Unit,
completion: (error: Error?, data: List<Int>?) -> Unit) {
// rest of method unchanged
}
...
private fun postProgress(progress: (state: DownloadState?) -> Unit) {
// rest of method unchanged
}
Zaq sa xemd fa yuaz.bm. Uk xci ciil() roftyiid, pee’fz soj kua am eprab el nne mbit ubmtiysaug qex wawpbeogulk huyu:
Pasebo hzu kima tun hidtyibf bqi Ante hdufe coi hitobah, ufk tobgahe iy hewx yoxqwect fik humr:
when (downloadState) {
null -> println("No download state yet")
/// rest of when unchanged
}
▸ Jqud druozh cawxob ar jda mizpamjouv ewi ef rakmoteyg ccdoc?
Wneori u gajhjoiq wvaw mel biza i Jenk ij EcyopnitQecliyhz azdibdh unc hmu mozh eq am ubit ag Xemvapg, ipw pukihx rwopxox wpi amac wey tuqpoloovy pijtb ur dbo yixx iy kewbunhy odvecpp ge wez map wbex zfij’ga yhroyv va zab.
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 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.