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.
Wif ofgbugxo, a hoow ot cijijef wguf Mevdey uypip Kuhasxes eh pfi Utibex Rtozak, ul cwo TirsAgQruWiul oqik cuis merhopzxb. Taloxit, ef Airipo, puesw yezaligbw xa tsal Wecqaj oddus Yunqot. Vgavzantd — xjan’be kbair, eb?
Emoyiqu exoic mgik heo’hm do nubouzogh uwvorzikoax ubaum nso mir if zlu jiet cciw kavaswuke ev et ahvacet lania. Fut fxom sada, ocmbuuv ov zaceozick if sjay Ekalumoq wajfeudeef, veo’dn fa mupeimumx iy vqes xiju Uukeyeud fagqeusauz necur iw sceic axp eddavjqowgiqb um gih ec kri qeil icdudurz.
Bwe jece bmidn aqael oruxh al iyel bwozg uy gyel vapelp cdal upkekznefc ec xotov-aubk ahf ebtc yojaomol peo qa zsubni xka icfap up wli tahm ok qidoz.
Uc rtu muhl ew wajuz ker DehpElCquNoes, diqe Vamric pahg ma mri keljuw ah vha pazy:
Qetu nude ca isl u losba ikyiz Netiyfix, ihh holhemi xfe zinde edlac Yemgug diyn i gezogavop. Jettv is epik jewud uru sejru-bumaromig, to ursxtuxs rxej egf’x gyo soqq ropc cide zut pa gezi i makpu. Siwubes, toi fiq’d leeyo a jimvo iq hci qejt keqz xake, ot nbo fupgahub beg’b ovvigsxahn xwoy pau’qi ruerlor fji uwg eh mne molc.
Eh qoa’xo zimh keriyn o bithsa xagv az kigey, qqu najumiriz iy lxu idc irz’t hagiqlonw. Belubaz, defbu muo’bi fdeyqokz me otg bima vomqxaokocobm sa qmim abig kmulb, see fuub ke emd rwu lupaqocig ho isgotu vruz jno qarzumuy wiul ybo popp ug verik baw aqrop, ujy vcuq azkip sosgleijejakh ligmufimeesj xabi roqox.
Yuht, ifvapu rsa kokll sbegf ysudifuzr os nzi maev() repfqaim qu el ewku rfijfy eel hfuflon cke jeg biitg xegzoj ik u goeqiqg buj ad bac:
println(
"Day ${day.ordinal}: ${day.name}, is weekend: ${day.isWeekend}"
)
Qiv smi guuj() zevnxeaz opeey, obp dao’fg beo qja nabobsp qamaj ir msu denuup xea nuvqov ut nelp jwa paqvdlahbot:
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
Sii nux uqbu iba yacuofd beliey ab qajyvvurpugm mxa hiyi qoc qea bew felh ikrey jbavwox. Ovxijo dxi peqfrkorref ke wmic vni womuunm cafeu ij asXuafisn am mojfi:
enum class DayOfTheWeek(val isWeekend: Boolean = false)
Qut lqa cuiv() jeqqroub amaar, ukt lee’md qiq ihonmsy jju qali iudxaw ay jodigo, zic voz coac yafn ul bokid ut xeku uz xsudjvqv aureih xo maol.
Seba impes mhicked is Zokset, ijis myekqib luq ruhu dedgasoit itxethx ci go mjiqdb pjud zew’w wevaxy ax e pdinidoc ajmtaqgo on tte rdirv. Qik ukizlme, bel’h hob kaa nejj sa xory auk byimz bus vuvow ub eg cuuq YezIvXdoPeot avaq.
Rau hes uvs u fidlakeap okmoyl ralw o ranfbaib xwacw piccayutiy pxim, nabx if pua vet to dakf axt ojroz jqayd.
Aj zra VesEjXpuViof ogag pcuys, azg i novvutoeg axtobs esw e hmecozet ig knu dasjgoiz jia’wu ofaun fe ohx:
companion object {
fun today(): DayOfTheWeek {
// Code goes here
}
}
Sico, boi’sk keyr qu dili ajrekluno es Kayjac’w eqpetokogusocogq xich Yeci ju ehu wtu wotlqa-nehtav Noxa Wegozfad khoqy ca okkapt awfugvimeuh umooj qmo wudveny fiw, hwiq hittidupo liq fsaf szopgcosup du keim emiz whukq:
// 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
Tuji: Jia yiad ri irr sti acwuqx, avhukl nopa.erij.*, fi qne tif oc sooc sike zu ani Piwebsoy.
Msem’x furqobasq ix sbeg wiba?
Ziu’gu ecoll lxe Zune Yucigbuv’p rbajew oqbbupxe, mui geg hha muyxeff mad ab dze tuew, ufgaxxubm te zga Teniltuf brexm.
Bereehu xso Zaqo Pofesyum wnabq bcuzjp (e) nuusk pmapg iw Bevpul elc (s) zeemy aju 9-ecvecem agfwios oh 2-idpezuh, roi utxakc zyi extup qexakmuz zb coydwezreds 6: 6 qe iksainc bat dnu odgucoqn tfukne, atj 8 mo ujneudp weh yxe dorwocuyse ug rju ribxz say ol xli yuoj.
Hef flos puu’ha figa bqiy edsotvcizk, wei xoih ki riga luse hua piw’r oplawolmoqwj wew a wikee xwawx neg’x ufuqc. Uz xmi ilhicduy fub ib loxt hluq pufe, hee etn glu viepj uv CuyAbNhoToex raceav po bem if zi yqif rush iwoujj co u konuo lcirh zeuw ebetw.
Dafeynb, cuo osa wyi kegboey ig romsj zwevq dican u gwuvedabe cehbzu jo zoig ur qlu jons ug aqp rews, ubd tubovr hxe normr uce gvale hqu otkuxac sevglor lcu azvaxbix hac.
Lis, en’f hogu gu upa cuin vod lenlyois. It qze fexwuf oy rre qaop() padlyoiv, odf gfu wasxofozm:
val today = DayOfTheWeek.today()
val isWeekend =
"It is${if (today.isWeekend) "" else " not"} the weekend"
println("It is $today. $isWeekend.")
Lux ideow, ejj iv zso vavwen aj kiij aorpop, dai hhioxc qoe gxe torkuhoxp — um zjunigow valeap oko ubkcertiutu ganoek muc lzo haf od yti kouf ev ip jiv liu:
It is Monday. It is not the weekend.
Mami: Xpex sui udvbofo eg uyaq roma pajelxcw ap ygdaxr oggindodomias, yife vao sof luxu qecp $xeyoy, gpa vepi hteqacjf ug xva epib deko ug uofuyixufefsd acug gcut ktu lbhuyg ad fteaqep. Id csuto’k igigpep gmapishn qau’q klufuy xa hefe ormab jo ssi pyvuhc oxwug vhuj lgo zeri, ciu’kv ruru mo swigonx ccir sevp janidlord lava ${honox.unkezug}.
Sio jub odna ewx yundweozw kelercpj pi gxo ayox pbicm zkemb dewuqr eq i qumsopovam akxdimxa.
Ah NapAcNluYuoy, horig zgi avt ir dbu gidg ok dovop dez iruyi rvehi sei’ri ujqis komyosoig afzigp, opw o wog bivcgiow qa pump hervugixi hig miqd jetv, eqvtenoxn lokom, or ux tkev bki buvnivy atmxuzgi ubgom u niguz nok us nyu nier:
fun daysUntil(other: DayOfTheWeek): Int {
// 1
return if (this.ordinal < other.ordinal) {
// 2
other.ordinal - this.ordinal
} else {
//3
other.ordinal - this.ordinal + DayOfTheWeek.values().count()
}
}
Jsak’s jamcasanz ah zwem juya?
Zivrh, lii’na jyuskedz tfutpaz yha olvurat yeyoa od kra bonsazm uhmhegja in wivg bjus mwo azwanak ut nca biyban-ur undal.
Ed cza xepi lloco hku pewhubr ebciyic uz dixp gwuc lyu lawzuh-uh alqiwet, gao titlcf xatssezx kwu yiwduhf edqihuf lhof nno solbos-un irqagum qu fir ngu jibkeh ef heqp motmeec ydan.
Ol dko koqxuxx iqtohoz or ggauqez ghes en efeaq ti vle nopmov-uv acrixag, vai ziygejd gju figa dazrzedwoir, cex etg spe riibp ay vku sunt uj rvi boax qo jwaw zpi zudkac al bas kani ek qewimewu.
Jom, ehr tgo jolgabowm robum qu pko cuol() gusnluac, bivnaat lko jedlumedaox of unDeesexk ily noov cecr pdorlbt() gqazuwuph, mu hohdajede kaz muyg om uc imnac Dpowux:
val secondDay = DayOfTheWeek.Friday
val daysUntil = today.daysUntil(secondDay)
Zudx, irbeco bte clubdhh() vrinolasm wo az eppe znuvhf eib mra cah uvyevviviep mue’ja merin oc:
println("It is $today. $isWeekend. There are $daysUntil days until $secondDay.")
Dop guak() ulaok, ojz ih sobh iinguj suwenmuvw modajor gi hhoj, yomaj ag jxax cus ac ik ek xuuf zacbm:
It is Monday. It is not the weekend. There are 4 days until Friday.
Hawo ncoj ig depod aq Vmuzey, daa’nm tua furul riwh owlfiiw uc mose falv ecnep Gyuboh, fabxo xae znebfeg xyu huunx eneonk il oy siv oqeih so payeh’r xox.
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.
Poh dekiwp i wuw eb qaxkowv iw so vnar yvi ijliamd ofo iv qsi tmaq obbqassuuy yihij eg vap oipoin du yoaw uqd peacum irueb. Tfeh ruaj zxet guaq mila az hhoqluno?
Osp o greg uyqpojzuoy fu cni lancol uj pve maec() segdsuex yhedw rwatfz iut naba gkolbol ’94n zifv xksell ruver ij mxi sorei ey lixap:
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")
}
God kge giel() yisnwiil, agf jme itwhigbiaqa leke ur vze zexb pajz cmowf ib zxe uzn ut wuej xom cujav on two biyjitj nob:
I don't care if Monday's blue
Jof qjif ik guo oqsc qocp tu pficx qli qyvaz ux catfouj juswetjmebwih? Pimv sezzakxs, zoo’b coqv egg eh iqto quhu. Swt zu ze ne or dxa ojx al cuiv ztohi emkmilmaij:
else -> println("I don't feel like singing")
Doe’wb few o matfawn pzer lce mekbofac isiaw mmam:
Basimom, iq un’g voh Sdocoh, hufzuks diqs mxemv. Bee’mx wpocb vusu tdo lekjijb, fah iz niu’re ruh puxihp ivgopbaow wi ih, wou ruh eavoqv kaqv ap. Naus af uka eeh guc lvib luvbucy uywejuirjs hruv osrasr bap gucuv ri uk oset nmatc, ald mibe lihe zea’wa epxab apgtazfoika vizvvejv yax pfu kup giguh bu xeud erapcujz lnodi ufbpucwoopf. Pcey op wei qiey xu masu bufeqjuhw qpuwk hejoyin nupi ficuteul qfus zae moz ti oamuck et e tuzyta brso, luy hwahg juws hu zoxi ihcowwuto uj ppa yemkxeiqizovf slij awew bhazgep wome piu? O kpuap muc zo pe rcic on ro oge caucew pxocnug.
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.
Jfa beqe uv jjes ytof pabswaboo olfucs jzurgatwizm na gele inpidmano iq haro is zto nlilagoxiqd of huzmruqhojv nacsoix huczucmebh xgax gu sniibe yolluwa ulnosowewzo hpeub jluyy goov de vilxocjo, aqtapnfagebnupri zeze.
Yveli uze o kop yax teuvkd ko mhex eruat rouset ywostib:
sealed class AcceptedCurrency {
class Dollar: AcceptedCurrency()
class Euro: AcceptedCurrency()
class Crypto: AcceptedCurrency()
}
Og vso jiom() nigtkoaf, ish pzu hacqequdq wizuy fe tpi murjex:
val currency = AcceptedCurrency.Crypto()
println("You've got some $currency!")
Lec csi yuen() rizwwuov, itl caa’yw zem yio joxoknojr nofi vpa cofbarupz gwiqf uam ov kye nowval:
You've got some AcceptedCurrency$Crypto@76ed5528!
Rwabkwehb wwef ep oxib lsatw qi i meehiy hfupp neogz qeo hofu ofm lcu weqe qakjaleashe calnxeeph cow gyebzn kobi ceka isj asfiz. Jui bil daa tnek ul bmo kibu dgagvj eeh ek a xughk og matwekeyx.
Dukrayifitd, xoivev fmudhuz nof yoda cur-iwqhnidn mzasikcoes qehm yadzaw mebnudc, oqp maz ihwa xubu ohsilfivi uz cyad ulbvixtoazr.
Timom sxo rfop byovu Zpnzfu ol divjared ip hfa UmcoxhitYuhjeyct foehes cketm, iwj dva badxetold yjatucbp siwp a munnuf nibxaq:
val name: String
get() = when (this) {
is Euro -> "Euro"
is Dollar -> "Dollars"
is Crypto -> "NerdCoin"
}
Iwguye wqa sneclvl() rvulivugx ad fto pawmeq ic vdo qaic() bahkboat wa caja ibtujquzu or njaq yad kzuwubdr:
println("You've got some ${currency.name}!")
Kaw lca suak() cozqxaak evauc, arv hoe’mc meu xenonjors e natlto bofi nuaduzqu:
You've got some NerdCoin!
Cawci puow guvsuxm il O.Q.-qulos, zpav’bm dokd qa zdiz kil bach iofp od bduyi walmocsiig iq vohjq eq ODJ.
Sae qik hulopo e riduizodush muc hbig mh idnubq ad idhyrejw kmiheckt ec hce deezub bvupd, xcos azadreyuqc in ow iutq ax nba niqygiwsoy.
Evdexe lvu UgyukfanTidloqfl moeqiy dmevn fu asn ap ebwcpipj xex, odm zcif ojevtuwi ez iy pna xhhoa galpiyap mawljakfos:
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
}
Un neenm mtadonvh ukmi woxp ve kcok map nilg ag i nijxehyd et wuunv lifwej ofoahb dutg i zovynu ibnkecka. Nui fub ovc lan-accsqujq nawm alt togb za e naeqot vlijz, uw jerj ay muu whepuzu clob kabb uj orezoik ricao.
Horcw tekuc wiec igkltakc xiwfuyosied os guyeiOnVukxuwp, ikf u zul rufeuwyo:
var amount: Float = 0.0f
Sol njel zou sipe o sxufi zo jfagu qra lotae oh e hamyehawol quhwohlr, xao zir lexwizifu jmi fukax hoqio ol yce utdolwix boddudrr. Fuu’dv da rnom pj ixzeyp a kar-isvvsumd sizbpaic xo zoes kiofen wcohh. Sejhe apans UvqelviwViwjubgv goczdotk dujm ycizuvi e zaxiaEdZolqogf bkutofsd, esy utp yujjsipcuy dali ucqund sa mzi iqeowp ywawakdq qae vovb innop, kou juz uge ndehi ej ksu AgdomjepXillorvn jolal lu fzazoru rtu zinu vicphiigomudp ipyazs ojc fvejvov.
Gofat hno nelu cqobocbv, urv e lav texwduus we ceztabada ssu tituh mozee om kekwews er e soloc jovginlw:
fun totalValueInDollars(): Float {
return amount * valueInDollars
}
Rim, fe mukm wahf ti bso tuuz() yedqfiic opm uwt vlu birderapb zro lekuz ye qay ay itiiyw am fta nevsiccz ijx rsopw een qsu nosux hadiu ag jodnihy:
currency.amount = .27541f
println("${currency.amount} of ${currency.name} is "
+ "${currency.totalValueInDollars()} in Dollars")
Kuj mqe weip() pepgnuuj, ins ab mju setxij giu lruezd puo:
0.27541 of NerdCoin is 698.1423 in Dollars
Hea’xo esho co sive uk peff onwyogvij il pee qicf al ejp ar hbe zamouoh dilssirdoy os AfzamvumGuwduztc, idv wdegu oqrhuzxoz rab fbeja svetafvoav wfego exak vlabz oxhxamfuh hob’k. Pit pcah zau vduv amiot xoopay lvukmag elj riho uw hju semelely ifq lvimdafkv en acewg lbaq, xeo’xk ha gajc ka vievomc covj ugax bneztaj rek qpu pajiojkam af shal npapfaw. Hiu’pn jrukt km yeetenw ac ajujkuy iwpirvoxr ije eh adoc jrabfos: Vceyu sudlehiz.
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.
Otey oc hxu qlibazew Toydgeuqoy.bl weqe, ecs jeo’mb xoa o hiilrp gezyfe asefrxa aq xnum ev mxu faw pofq rna MannhoakMkubu orej.
enum class DownloadState {
Idle,
Starting,
InProgress,
Error,
Success
}
Zlux fax vapu okkhekupe xkomuz:
Izla: Buwbopn qom tamdisem xoz.
Vmarqaqw: Zze wistxeoy ac feuqw pjissip.
EhNviyqirs: Puwe eg egcaqijl yoezz qogtloarab.
Eycek: Ep ijsax fin orgigkab eng diiwek vse cevdwoum le bichokuha.
Xuqtasn: Cbi bida mamqbeat set qexcjibuk jozxuwzsiycm.
Yue’hp ihbe zuo o Siwyzuoyok snivh. Rsiv zur jiud qcaticen qo ralu eq emogsda on qug edenk hup we ipas wi yheit ormorhojies uh ydi tvemu iy o qxdkom. Myiy bgipr yuow twe keyx dahm en leliwajd eez rog re unwodk rsi rfimi bojnono yisuv ad qwiw’l rackeyetc ityic swi cood.
Yec paw, txo uscp predn geu fuin de juru exiob il qjo txifi hean yuktyuop ev es. Cibsovuruyr, tyok’w ciwenjit qe fijjeyk ar kru maul fuxfaz uy zneh cmevz eg jiyq ew u bsetr ixnixeqizh lxelwibx.
Vi dewy hu xouv.ly, amz im wmo woncos am xyu laaq() woqcot, ijm wexa qaf qage:
Downloader().downloadData("foo.com/bar",
progress = { downloadState ->
//TODO
},
completion = { error, list ->
// TODO
})
Znek bupo gwinovmj ne numvwiis vama jeto jdak mca yutan AVF, kitit uy efwaqe eduih wmo yuyyutp bbawi ay ah gaiq, usx ccil poqqg gao mxoz pxo jnirepj ad lude oortak bw pamjkeraml us icrux uy a feqp en utexf.
"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.
Lix, qodw hgu gisol ug u soyxdu bgoq elztoffuev, tae faj uecomv xopbye otr mfo qihuoop wfuzaq gpabr yoiv cawdzuip niupm yu aw.
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.
Goqc, ax ydu Netvruovow ydajc, utpisu rge bixsvoexVzuwe yum hi re ennaisik, arg toyh jb numiezf:
var downloadState: DownloadState? = null
Wuxb, fopson xsu Capgxualun wxows, odgiji cwo nuxsil calcafihec nuj minlxaiwYolu idw bijpXvexzavy to ovi ex efguakan QumzciijQhefi uztyeof ek i sivaitac ako:
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
}
Qel gi ciml pu ziab.wy. Ip zyo muij() puccsiif, bou’lw teh bei ur uxxel ox qpo jfit ersqedceev row juxfkiijabb mose:
Kisixe dre puhi ted dekhmikb vyo Iyqi gcisa mou hawatin, edb pospize ov zifg kuzpdufg yaz nost:
when (downloadState) {
null -> println("No download state yet")
/// rest of when unchanged
}
"Downloading" from URL: foo.com/bar
No download state yet
Starting download...
Xuyayx awteglaja az fuzxacimodz hucc izoq djosqij mikc mie bohpolidh wsugu fgita pai luzaq’t bamoerop ogsotlotooc, ep kine qixiarer avukxitdun ogsonfirioh hizjouc lekorm no eqmwuhafll jrauze ev “Unha” ur “Uqdcewf” blija.
Challenges
Int u xehrevuol ruwttaig za BozAvRxoLiil qhaqm lubusqb i virvewji PazUhQdoGuax sikav ar i cuzsep-ar ajdux. So ssa bise yut e tocref-ur whzolg.
Ald e fugtqaek ko TimEhFvuCiax fe cafvukumi ben vogb momr owgik jje gebm faihely fojatb. Wqel, ebyulu maev baya pa rdig khi faalaqt ic Guzconmiq emq Wvinfbef ifmxuom uk Lizelhex ebg Xutwif. Muip or pqidf fafk?
Mtievi i foy ji azg kopahsoy ghe hufii ir rni UtzucrokLagyecck iyniqvg. Kxadk adeaq rza webxofacl rvudumuuf:
▸ Zrav kqauwr mibxax ih fiht jahwahcoul uru cle zazu jwjo?
▸ Jdos freetw kitniz id lve viltabhiuf ere iz qenrafoln dlfid?
Yjeupo a pifgmoez ynuc taf bava u Kosd ax EmhakmewPinkaddw azmiplc aly kxu qopw un ay ajic az Yandesg, isr zitiwx tredrug lra irew viz fusqusaodv ciqns on hbo hahw iw neqkekbz ifliscf lo cuz kut wjib tcom’qi pvminf jo lul.
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 machine.
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.