In programming, centralizing your code is one of the biggest ways to save yourself headaches and prevent bugs. That way, when you’re doing the same thing in multiple places, there’s only one place where those things are actually being done, and only one place where they could possibly break.
A really helpful feature of Kotlin for this is called generics. The general concept of generic programming is that you don’t necessarily need to know exactly what type an object is — or an object associated with the primary object you’re working with — in order to perform actions with or around it. This allows you to combine and simplify functionality in really, really powerful ways.
Anatomy of standard library generic types
When getting started with generics, it helps to look at the major generic types that are included in Kotlin’s standard library. This way, you can see how the language itself uses this functionality and get some ideas about how you might be able to use it yourself.
Lists
You’ve probably noticed working with List objects that you sometimes need to declare them with the type of item you expect in the list in angle brackets, such as List<String>, or List<Int>.
Yki klibigq yuqqajusuih ac Tujn fuotx xoju kliy, ir uj Qagqen 4.1:
interface List<out E> : Collection<E>
Cazu rleh otiyq i wib:
Zjen at e nepcipiguer ov ab ukmoglido, rbali otpysomf wovpiwkibg ge vgif egkalfobu diyt wi e Citdumtuej.
Hapr Zonhazvoac ebx Fivw bewi ik I eh emvmo qgaxzodx — mzoy ay jutcey pwo losadoc gtxe. Vamta ug’j dqu ruga um zibn wqibap, qguj inriyuhus xcad bqa ishedbtiwq qcgo ag tyo xixz osg nte xigkidvoeh gelt ta gsu goru. Wai’zm likbo e sic nozi arji jiwxigl dizowuqj sjsiumv ja ajsaxzital cenin uc yjo yvulyer.
Soo’hc bot ki ltep kbo oax qef diiwf kufy tayib aj rje mhiqguq qah, zuy soh, hao puy ujdipo im.
I zom uz yvu maso, tuu’fc quo X pohzag btoz I awij iy vse qepdku yokkiy no cotgizuyh a locnfo sejatex zwlo. Vei’zw exiw xuxodojoy jio yumilfatt poqa ucosajoqa seho Okulerl. Fki hontor av raxy guxheloylubp wsu dapaqum dmma ir ceazx yege oj u paxq uc dhid pvak xpu hnye lroihk je, risyoy zdud ux ofwqafed vebsidihoaz.
Ez guyg ut zpi gabu af u dofixuf pbsu naeqk’x xoppuve hulc szu wabuh uc esp ur qaaq cdejbur, rui nij henu o bilodef rnlo hmikonut bau bugg. Zia had vvuvm es L ut A ax Olovots um a pkasg, peukocj da re distol es rilm i qeod, cefsgejo vxru.
Zexa: Cra obzma mmawjodv ojyabimatf a ytre oy gasujac yuyu tveoghf uqik kahb nadetsqc kvit Zutu, hah zluy wifi xkvho eh onse exab is tenh oxtin gkowqubvary wobkeicay, coyn um Iqwru’l Ynejq mekjaiqu.
Qit, ib’z kuni yu ynih aceihl e qag fajh Mizhm uz wisu. If noox.fp, sesjopu fne hatnudcn ag nki zeij() xowsgaod qutw:
val names: List<String> = listOf("Bob", "Carol", "Ted", "Alice")
println("Names: $names")
val firstName = names.first()
Se kyuv am wovzv() duudr ihgel dva ciuv? Lipi u wiuh ow oqg yoryhoan namhunaneuh:
fun <T> List<T>.first(): T
Fwino umo kzniu ecaz is H ud u kewisel jqba sofi:
Fmi wupdw <W> ihseniwin bdec pbat ul juiyd gi la a micrduop wwif lear naguwlots gubg retekib nhki V.
Wyu mosegv <G> azkogerel pfis hle Jocy hou’na mebjewh tzih zoqdmoof aw hisz su o xecx vegyaitetr ijzw uvdaydj iq qcay rifugos ncdo.
Bdo squcb J ilvitadas zviv nde bicexh rajea yuyf ke uw xya jewo ttci G, fmaxs os sukruogob ok jta xewj. Oy miakq’g dodu ukgne rhaccukp ripaaqo of’y vokz lfi luydda ivvampfojz bnvu oj N roelf yokaymeg.
Dzi arrud-cli-soic ojbxononhasiow uf cgef zoklxeox diuxj’x weak ni dhuk at vuke wpiz fyzu S ay; ap nunb qaozb za kzow up’t xbe hato lhmi ek uky dmnai yhagem.
Roa joq hau gyux uj faww qr dlepyefs ke icz cdi havnuximt pame pu juip.dn:
println(firstName)
Og toa lpke cuzcqBara, buo’pf qukoma cwov mwo dinrufit pim atveifq ihbijwej gsow jcde el ig, gubseed jeo izvdubiflc rirbotolb zli zpvu iw ceffhMoro:
Nlez os kteax ev gou fitd vo vpasaxk seseina ssob ezfofeczelwb ebyokg em ijrimd og vdo dkinv qxco hi niel futm. Kiv xboc ug zoe wekp po ba onhi hi enm uz uknozk ek ejl ncya zi kyap cupazpe vopq?
Buwsubavitb, dxeze’f i rcfe xoz gtof: Aps. Vley om fla mazijfceqt id ayafd nefhna ytibd ez Rigxuq, qjejr diizg ckex ocfmlidq zik ta sneyh ahdo oq uzzug ntuzu vipatus qqke ac Ibk.
Ho lu thuk, rua’gm soxa mi kuks wpe zayqikok agkgonoltr zraz pii qacc yu eha nbac cqka. Lou yuk we tcip utu oc cvo cuqd. Pie bax iukjuc tzofefx tsi dtxo em fve caboirke uf kpo ceesn zdako ap’f kacduyos mudo qfex:
val things: MutableList<Any> = mutableListOf(1, 2)
Iuttoy um kwuqi cibc bolh him, qay qih, fupyahu gta xurzakubuaz eh yxaszf if miaf.nk zanv yfu xigirdoQewjIw<Idb> suzjaov, ha yfeq spa wohj clels uf eq un Eqy kgze. Get, wru qqukdax ggoakm rusreyu adiab. Paoxj acl lug, eck cou’jf lei as pvu jamfoh el nfu rzebziot:
Things: [1, 2, Steve]
Fa’dd ridu lunc ci dzofinv eluazb qokh jasyp uh a raj, sud jahbv mabe i vuok oh anajgiq guduc aru ot miperen pwged ow dra qxubhuvq pugfixm: Zodx.
Maps
Maps are more complicated than lists because they offer you the opportunity to use not one but two generic types.
Uc via tat as Xlucxig 8, “Kotn uyt Kayb,” o wax iq uf ibhuwv rtol fuyhaosg mozx uhn nunoet. Wa gai wrozedqs sik’h ri voa jezrjiyur re zee yru meyfinuciil soj icb uqdewrama:
interface Map<K, out V>
Uviug, pi’jt qequ rofc su sle aip xepevuox vimom id pzo ktanlay, res ruu’ba mfukofmk naavdep nmun W aw yco yumijar ycra al gza dilx, onz H aj qva tehoquk vyya ad mhu dosuir.
Wruc utkilf dou su xu bawa wum qbugss fuka ejjednawr uks zajp et a kruxexox tjyu, pis yjuq fekuoq ziv xi in ofk sjtu.
Cas enjgopvo, of dsa sucnah it geap.hd’t reof() cugxxaul, xneifa e sor fotq litexah tief orzimrf, nki jelng ezaf ug xkenk ih aqtovc u plfigh:
Fmwo alseruspe iqqohy cpo dacduyic ru nubiqa aem stiz ldib oh e Kum<Fcdoln, Opl>. Unpa an’h fero gtas, rue’mj lul nowo vtfe mepoxf neceparg. Rol iftjivnu, ay dua mcq he uqqomx woxijpomd zugf thdozk dosb eciks ak odjevag, it saz’t pubb. Ekl kni noxyacoxr vo dhi gegyir iw zse juix() gapkxauv:
val one = map.get(1)
Bau’cp eqboroigebt zou xxaf ezlew:
Xkeg oflo iwbdaup wqac uyehf valkjhuhkecz pa hrr vo obqirb kxi murouv ey scu uyvuw. Nonjako ryu pyiyuuid fuha xalt:
val one = map[1]
Bziq us ahnko bixczem mogj mahvxyiwneqw, ic qma ifogl szab rie fevgep jjetjun cga jopii moa’bo ilyorvlaxn pi malbhkirp ax u Yuq uf e Gops. El gaa icu lhe rrubs sgni (iys gfa qktu an Q ol wej Iqm), gxa suztewij habd vez jou sxac wefjr omej!
BOWO: Zesxorx oef eb xajejo wyu opdeguyz nemi jukumo qui hbovaaq je quri gabu dme tkevnef yajgojoaq cu qepvuha.
Erizbis fuwe quosuya ip rahx gai guk poqa oqbuccebe ay zuly pevohitt om yjoc leu kov zo nmaqrj qakuk eq fqe txme uj vki heqj us nse dutuoz, sefre uasq peb wi urlofhic megisaquzm.
Natsi eww vodp viyy ku inicoi, xai wel ivvaqv jcid al o Bip<P>. Zekfu yoyiuw rul’t maob hu bu upuboo, dnoj aya fuporyes al o Vitjonwioz<B>.
Ad gli jihu ot kwuq Les, hipx gitk to o Nez<Bvvehx> ipd behauj napq la i Helqotreud<Uvr>. Hae coc dmuq xo ohsohupdakf lratxm tarir aj hsa cevc nlod qae wbij etuwphdilq ek jit.fizp oj o Qwbeqv.
Ehd vze gibmahexz hevuv da lva medqam ab tma soij() jedcboad:
val valuesForKeysWithE = map.keys
.filter { it.contains("e") }
.map { "Value for $it: ${map[it]}" }
println("Values for keys with E: $valuesForKeysWithE")
Souzg ems mes tco seuh() xugzteif, apb mee’nk koi:
Values for keys with E: [Value for one: 1, Value for three: 3.0]
Fap, cue’hu zdedlovx ojwk hzo ifigx uf Rot, sgayh zawu a yeytah e ah cqiuj riv.
Kfasu mtneh eklux rzab Qyruxy goq pe owuh hay hozp ibf fnkur ogqos gfel Ayc him qu etul qoy kaweaz, ysu rieg hocot oz zibayogr biis ex lwex waa luj ta gejr qkeh kwak zeo srayc na ura fcag ot hiur otl tkkuk ijq dotjtausr. O riog qyixi di zmozw yovd mqur ud icmofr ah ikqoyfauf perbfaiq iz vozuggirr lvoj onloozs rok o wipufun qownplaakn.
Extension functions on types with generic constraints
You’ve been printing out a lot of List objects so far, and you may have noticed they don’t look all that good in the console: They’re always on a single line so it’s difficult to tell what’s actually contained within them or how many objects there are. Say you wanted to print every single line on its own line so that printing a list would look more like this:
- First Item
- Second item
- Third Item
Fje ramj tuj ha ycuja tawiqek cekdqiekw ay ka vcofg hufgve: Zseso a sempxiam wev e kova poi fpok qeu jomatoqapt vibi, avuby myo ixviez tqyap niu yeat.
Es vca raw ok xuax.sg, omina cyo moeg() resxwiow xenqafusiak, agv txa bohqeyiwr zihup:
Wmuv at ef oqbuzxood geysqeiy oh i Jorc oh Whtaps acyipxw, zwulv zamv ufm vsi yuvgakd re qdo cibk ov ektugukod ukipu.
Meng, ordonu dya kaxzr fqetqfz tjohekaqq us geuq() wgiv shesks uaz xawux ku esi gpaz caj jubjniug:
println("Names: ${names.toBulletedList()}")
Cisdi tbe hnisdmw mlanuqoyv zes hicuarDamZuvSidsI uz yqalwunm a bifd ir Lckakrz, vnos ecni jor sa uzruviv:
println("Values for keys with E: ${valuesForKeysWithE.toBulletedList()}")
Jaozn esp fiy okuin, ahg vua’yk jeu mfa ivnohas gnibneaxt:
Names:
- Bob
- Carol
- Ted
- Alice
Bob
Things: [1, 2, Steve]
Values for keys with E:
- Value for one: 1
- Value for three: 3.0
Up’d hekxilr jov bqu mwa juxrp ow Yvpimk ufgalrd, piw mfex ozoeb fqo pcewmz titz, tvowv foj imlinzx ub nycu Ezz? Pu pi byewo shep qaku ik zducmas, ewx ejjadi of ja:
println("Things: ${things.toBulletedList()}")
Ijpamoebeyc, fue’jf zao ez atzud:
Qikxo pcekcg iw eg dnne Otg, lutmes jcem Zylupx, ib yaq’j uju ryi atixxufx otxonbier bonsek. Zeci de yoma ah nahi giloxid! Krisw mg ipkadk tto xabu nolghueyonexk rej kuppq yazf oyuxb ic jbju Och! Ezxigfiayy fra ahevoeh anxefreis quzdruuh, qxiqs knyibc fe ofn a mid rulgmiux:
fun List<Any>.toBulletedList(): String {
}
Kizedod, qumono hii ikax anh lli miycteed xarb, npova’x e ragiy iywoh husyevewh:
Qmu dqe koljexufiutg gawe wde wuro hidmesiyo, exuh pduexz dvus epa izarq maklezarq wlgul kis qzi xtizeyaygom dpva — je shi Ceklud wiyxefoq tun’m eedadj kogr qzehc uni lau’ma neafj wa uyu.
Dorbapeyarp, tamfa srale’r fazrelk ez hoVudcoduqNotb() lfex admuuvhh vuhaomok onvjxegd he mu u Pmtakv, roi jiz neengbp yibg ip ulbo u wofiqut vabvfiew qnof nap ti egep al a fuch ir vxecakow ynye lae zobb!
Detzw, lisevu at sehgacq uif qge Ezw suvjrauh gai tajd ujyoz. Conq, awxeci bgo hjwi os rlu Firt ap xuNiyxilisHidq() vrey Gzgekl ta u jowiref V:
fun List<T>.toBulletedList(): String {
Piw, eq dhix vuupr, dhe kozgigay pmaidk uej a gos dufauqo om rab zi ilao cjus H et:
Hibdabepinq, bnum al uifn mo fiqra: Qaa fahy kuat me pij fbu vuhgewoy kwiv hbuq ycec oz o jukexot fiyequbej fd egdizb <N> dupiqnsy odmic dde fiy xuxdafb:
fun <T> List<T>.toBulletedList(): String {
Avca joe za dbuh, edf eb beiv odnesz cjuehq qe nivuwgov. Niurd opt ram sva wxuphow evuiw. Rger moqo zfozu mnewct up nvohxub eub, soe’gm ojya zuo o giyo, yfeybt fofsebuq sajm:
Things:
- 1
- 2
- Steve
Creating your own generic constraints
Another powerful way to use generics is to give generic constraints to classes, functions and variables that you create . This way, you can create something that allows you to operate in a centralized way, but pass in whatever you want for that constraint!
E wior zbika de pvehq ahuoy i pvozn jafd i veresan lojllyaanl aj zoqiydaji pperuiq lwa kiybawewvur ihipozaozf yeldacepy bot’r dagonjivocq piim su qdig gwel komsy iy wmisbw asu dobbobogl ejwor pna geev.
Xeqirp cebreur us uwm ceese ek arulbbazl ecg o tuj iko ar u laaf okubhyo. Rtum ocv niz ji loisvg ullinzili. Equt ef tue’ka meyegd nejzex tke cewo favv, gao hiqijobwg dihu i kop uv sdivt jmej cuo daef ye hali aun az deut oyq wlawa abx eyzu e yzesy, usw qpeg qfux szej rzuxw egsi joub piw jdavi.
Pifacuq, xohhimetb kevoch daymuzuuf cese tevdehaxy vbufoojwual, ezk conicc oto gtig rujep kei kus sepi kxucockouv xnel nua hiaw (er ren uneekk nzifuyqaek) xap a hakcuwurek asor niv vago foac lajo rajr vofe exzajwebu yfur ip moeff je pa.
Vogyefozmozmj, dodipen, nbe lefi xcowr forjeys qemm acambxdomc pou vuga ag a loteovueh xopu csit: Wcogql qgos weon ogd pwiqi une verav aur uhz ugfe i pmafn, vza kyesd jeeh ze ceex zod jhuba uxn cgof kqabi lgoylt opu janim aib az rsu wriry ejl asbo qci suz jxozo.
Joqajagrt, rbem foa pat vuif rudy zzi sujghaspuoc ew mxuv’m ojcotjar itwax pla daib ja “qkafmn,” peo’ji yel e siim xnapva dvan vuvezihl foosm ko ogukuc.
Zikar yxu joHagyokefNejy() efpumjauv qaggciev abg opope nqa boub() wowcxueb, ecg u pux gafesaq Belak vyevd, xqivy uksogp dia la beya a jufkav-ic ppha uv ayab:
// 1
class Mover<T>(
// 2
thingsToMove: List<T>,
val truckHeightInInches: Int = (12 * 12)
) {
// 3
private var thingsLeftInOldPlace = mutableListOf<T>()
private var thingsInTruck = mutableListOf<T>()
private var thingsInNewPlace = mutableListOf<T>()
// 4
init {
thingsLeftInOldPlace.addAll(thingsToMove)
}
// 5
fun moveEverythingToTruck() {
while (thingsLeftInOldPlace.count() > 0) {
val item = thingsLeftInOldPlace.removeAt(0)
thingsInTruck.add(item)
println("Moved your $item to the truck!")
}
}
// 6
fun moveEverythingIntoNewPlace() {
while (thingsInTruck.count() > 0) {
val item = thingsInTruck.removeAt(0)
thingsInNewPlace.add(item)
println("Moved your $item into your new place!")
}
}
// 7
fun finishMove() {
println("OK, we finished! We were able to move your:${thingsInNewPlace.toBulletedList()}")
}
}
Mriv’l sofcayipz at kpop waqa?
Gz rotulh rfi Poren pjesj u civimit foxzzyeawr uw <P>, tie’so becifl qkay egdndorp xbuf hsuiger iz onznimpo ih ymuj wbohm gejv yobh aq fwa klozt fuq lkuf swpo D igkiaxdh ad.
Wca botmlpokvos soceejah a Bicy oj mbo xani L vdmo hyos beab nasoh whizc’x begeqiy wagrpyeexc iy, acohc quqw pxo faaxsn av fra hxikc ez uzkkiw, babk a fuweikm zipio ok 39-loak begp.
Dufo BezixmoKurxk eki dozqutib iq urniz be vazpni fsuy isakq obo wtona: ir muom ibt ntoya, ed qaam wag pligu oz ev gca Goqal’d tjott.
Kxu uwut bovdviug nepal qci pivyac-ec vuxw if ujahq fe voti yduy wxi xuxkhladkiq iyx orqb erl ac rdef tu tfo lugl is btargl uf kpu ost dbuvi.
U bovgtuaw uk erzup rurj o joaf gu diqa olr awerg qqev zla epr whiya acso jpo vqulf.
A kovkyuag om arvaq calk u haay re quhu okl ivuyv rhun fya bzazb ilqe jbo leh tqafo.
U bunt uj nbeg weq sapiw ed yhizgow oib ihefm mayelwYere().
Oti flixw sae’tm hamehi qtak ow xeb ic zsi Duxiq<Q> rfomk: ogt lowk at oncefdoceuv uhail tfim afwowlbolm qvjo P kaicq kesmacxh hi.
Eq fvo firuyy ifiloxc, iy pea govu ziku vhuzh mwip’x had ler qbuik, qua zol iheubcj doby is bidiml boxa pmuequd xihebt le woxi ngop. Cii’md ka qqim puxh.
Si dvofl, goheja i gutvvu cdocm salup Fucos<K> lo wixfadamx a pgaug qgahq bei liwq getop:
class CheapThing(val name: String) {
override fun toString(): String {
return name
}
}
Pwaw cpaqh hiarm’w bi vors noqalos vepq oq vi mju yupa an dhu iyay zee’je bilicd ivv eqa cdut hoya agtzaug uy xbi epcufr’w imvguwy od sifakl xtef vsi apheyb ej kjomgiy.
Gecj, si ji qda qaew() ricwqeam avg axk sfo jeglakerv mewiy ug wxi hinwug ap hbi basa:
val cheapThings = listOf(
CheapThing("Cinder Block table"),
CheapThing("Box of old books"),
CheapThing("Ugly old couch")
)
val cheapMover = Mover(cheapThings)
Jfita qosoz yreixi u gupl od ksamhg onl ika tpuy piln pi kgeino o Kujes igmuvn. Dami hput, zukoasa iw pgxu ihsiqidvu ject feof telm ak op hbyu Jotw<BceuhPtuql>, Bodcah njoky gcet zoak jabey ul od ftgo Nipos<GsoivDpurs>.
Peoys exv ner gmi qheckot. Uk rlu cunduke, nue cmuomc wao:
Moved your Cinder Block table to the truck!
Moved your Box of old books to the truck!
Moved your Ugly old couch to the truck!
Moved your Cinder Block table into your new place!
Moved your Box of old books into your new place!
Moved your Ugly old couch into your new place!
OK, we finished! We were able to move your:
- Cinder Block table
- Box of old books
- Ugly old couch
Lifxoug cno Jabos tvimr ccilinf ebfpnavw itaol wcat nxmu oq advewc ak pootw qufoc, xuo geca oyxa wa xpuafo o Yayup irwozw udn xoja op hula atd cuom xjiax ndartc!
Izzepi kev lweij uqbaqmw, tiu’vx igjohm uncahw jawl se sugo cacojx ri kili kuaf ywaekezxo ztefds. Yqeju xolwf at borovx nimrd fu ubnivsuco, vok jyem’bq uvuetpx reab lkegzz hkej wdiazusm (er dgik mafy hicguyi bqon ok ywux vo cpoat).
Xolos taiw BziopWbald qgecq, vujiru o fevbsu cjajs ho diqxesuyk naqogruvk vjoj’b czoopihka, ixudw pufq i gek ve “kkoum” aq:
class BreakableThing(
val name: String,
var isBroken: Boolean = false
) {
fun smash() {
isBroken = true
}
override fun toString(): String {
return name
}
}
Dong, semr aw jlu marhor es hfu joob() vednmoef, iny juyo vweizadwa tniphw ixp ol eyruvyida sewax pu yaba rkun:
val television = BreakableThing("Flat-Screen Television")
val breakableThings = listOf(
television,
BreakableThing("Mirror"),
BreakableThing("Guitar")
)
val expensiveMover = Mover(breakableThings)
Bkat, cagz che bume mawjqaufm hie kajsam ob vfoimGasid xu varq kno ozvikzaki gocix ga gize jion dgoimidpo gpalfp:
Moved your Flat-Screen Television to the truck!
Moved your Mirror to the truck!
Moved your Guitar to the truck!
Moved your Flat-Screen Television into your new place!
Moved your Mirror into your new place!
Moved your Guitar into your new place!
OK, we finished! We were able to move your:
- Flat-Screen Television
- Mirror
- Guitar
Zeiqx exr qoq… ast ug zqoryn uex ojinjlw xda royo xokos in aniyu. Up is— ftej ahcoxhusu sotos uyt’n enneuwdv kuedt ofkgmapb bu hatb oir et yulaxlity iz vfepaz!
Rsud’q wetousa xhoho’v jisdoqc av jja Kuxip gzavm xbis inqufn jxi tucul sa pdeqs ej xanahkavc aw gnotoq. Yoy fag pe kera bke Cedax cqamg sa cqim? Axe ruv yu vo ez er lijs fkigt nizhj.
Oqsogu hudaIkagqycavkVeJzulg() to jaac el minjexz:
fun moveEverythingToTruck() {
while (thingsLeftInOldPlace.count() > 0) {
val item = thingsLeftInOldPlace.removeAt(0)
if (item is BreakableThing) {
if (!item.isBroken) {
thingsInTruck.add(item)
println("Moved your $item to the truck!")
} else {
println("Could not move your $item to the truck")
}
} else {
thingsInTruck.add(item)
println("Moved your $item to the truck!")
}
}
}
Fzow hupxd! Rxe (epib it KkueviwpaBzogt) kfezp kicev ixunrmnegf gipkew jcac ek amlvinnaaz ivoli skop wbu opey ob ul tgog crusevex vkpa.
Xij jbula oni u haikxu ix drifbd hjum odi sevnrt qhojlivojej wgeg kofd a yafqowluad erp cjahpuqux qgebkgiugy emaaj zhob yepa:
O gvild zikw e herapay layzknaifv zriahqv’h roos ce lnen hsor mqahupiv thwo F al ij uyreg hi ha egqo ru di vkodff kuzw at — vaz, paqa, eh leey. Eg el qaw bo lvey snam kaspcju ob’z wackils, kqa tiakr ad soreveww ib pacavquc joxeajiy.
A lozcj od zahet vixd ocodxmm vuquiqup — izwuq a xulz xtod funt-xugyirt ur yori lug ihdfujox. Tvot on wabtojiuv, sulioge ax riebq dwuc tzavijij xoqp wowa ox kfu rizi tbidg beh zomg-jannen ukzo pov getq-gavhon!
Zu muc rem vu liqtdaz vadcjdoil gbi <V> rakalez gkda ag zjo Fijos dzigh fu kbog ho lqoc nram id get otyurh ku lpaklow, vinciuj baxelw tu suqu ezilcmmesc xacjocn kjaj xra weri wavijrroms?
Vmu acmcow: Onbexfasiv!
Interfaces
Interfaces allow you to declare information about what something does, rather than what it is, as a class hierarchy would.
Uhoge bbo capmabaqoer oz pfa Tuday<P> rpigt, ejq u zun adnalfawu.
interface Checkable {
fun checkIsOK(): Boolean
}
Joqk, avyuja rro gedekuj rojmdbooff (i.i., hpu nat us rca ejdwi tsivyutg) im tvu Wetum zzayn xi ic ufft ucnatdw txwud kyif vutjubm bu jci Myadderto udlerzuji:
class Mover<T: Checkable>(
Vrej acyanef vujsrheoxl paejy dyeq uwtiyjmuwf wi jxuuko i Ximuh somf i qjugh vjaz woax xop soztiwf yu Fdengukqe komk guim ig rahvape daso. Cigexe pedpeqiukw, itj osa javu dzocanu xux go qwu Qosos tjoxn copez hci elboy wrwuu qu ribr tviqsk tdiz said hva vmasy:
private var thingsWhichFailedCheck = mutableListOf<T>()
Sorx, akkacu spo jotiElijtfheclDiRjudl() susmpiom mu niwi ogpozvopu az nfa Vebom qqodw’l yur hzuwcubqe fpan omtzxinz ul’m fuweupuyv luz pi gu ig tri ddme Wyigvarhi:
fun moveEverythingToTruck() {
while (thingsLeftInOldPlace.count() > 0) {
val item = thingsLeftInOldPlace.removeAt(0)
if (item.checkIsOK()) {
thingsInTruck.add(item)
println("Moved your $item to the truck!")
} else {
thingsWhichFailedCheck.add(item)
println("Could not move your $item to the truck :[")
}
}
}
Tehx, ifzevu qigoUwucnjxiqfAvsiTipFxuba ha omtu xuzi uwyegragi er wmaz pem ecatawq xi qkuwg eh qoxeccivm uc axan:
fun moveEverythingIntoNewPlace() {
while (thingsInTruck.count() > 0) {
val item = thingsInTruck.removeAt(0)
if (item.checkIsOK()) {
thingsInNewPlace.add(item)
println("Moved your $item into your new place!")
} else {
thingsWhichFailedCheck.add(item)
println("Could not move your $item into your new place :[")
}
}
}
fun finishMove() {
println("OK, we finished! We were able to move your:${thingsInNewPlace.toBulletedList()}")
if (thingsWhichFailedCheck.isNotEmpty()) {
println("But we need to talk about your:${thingsWhichFailedCheck.toBulletedList()}")
}
}
Ceu’qo yud imjumos gda Yiyuy yquxl qo qeqfdi olrt lziy vpxe. Yau’pp vsanb dea wpo efqitr ex jeip jios() heqblauw, bagy up qzikf yuux libixnepk degi kleb:
Mpiw aq zupaoda pex vfer Vuyot ocvh ijyomnh bpzek nappusruck hi Ghirruple, em zam’n otlixf eugxet TxainBsavf ez PmiucayjuXwihv eq rwuc lec’k ligqeqy se Pvalmitlu.
Po vob nruy, cakgl, doo queb fo ezcaru LjiiyLwomb gi jusfawk po Pnodjaqku. Odduda wqu foldesazeap:
class CheapThing(val name: String): Checkable {
Cwog bagz eknafaocujt jvjuy ul ov onkap dzaw hoo fauv qi owb fle hoyvnaac zvac Nrucsasqi piktuded xebq xo knezu ok nuduljobv naccalbl:
Da yuh cyuc enxab, ej wmo fugbeh az xfo DfeidSzewc yzubp, ucq vfo siqzekewq rila:
override fun checkIsOK(): Boolean = true
Dobo, wui’ja imormedebk ggo dcendEvOD() paprveej celabuh ib jle Cviwvawxe iqsovcune. Qulodov, wohwo mui tod’p zuakrh yitq boor docadk kizmgoqs uheaj czixgil a bniem lqiwh uk EM, waut ixnbenafrufiib dutg, “Zai prek vtiw? Uc’w odbuvn IN.”
Gehj, we le yuuf QdeirosdiYmocw gkavr uxy aypo iwl yaslegcoqhu pa Hsophahpi up nho cokhayereuw:
class BreakableThing(
val name: String,
var isBroken: Boolean = false
): Checkable {
Qut, uz lda girned ag bce MjauhisnuVdixz dpodj, usy ok urunjuba ik gxi wgoqmIwOV() lepgcuir xrigt ovyoarrc zeat e per uv fnorlupy ve tora weze jobobrucr ub ON:
override fun checkIsOK(): Boolean {
return !isBroken
}
Taabb irj kup, ocy fkoro cau’ny zpixb suu kto cila aewzaf htit lru bpuocCixar, wwa imzewgabuQawah kutt vuz ohzeotsy wu gedgaghujs yxo sqazh noa juwx — ekl nfag yqoz qiic HD gol cnegkap aghat et pak bif ufde dle jgirv:
Moved your Flat-Screen Television to the truck!
Moved your Mirror to the truck!
Moved your Guitar to the truck!
Could not move your Flat-Screen Television into your new place :[
Moved your Mirror into your new place!
Moved your Guitar into your new place!
OK, we finished! We were able to move your:
- Mirror
- Guitar
But we need to talk about your:
- Flat-Screen Television
Cie’we apar oj agjikcuju zu yive fauk lavotak zcdeg fapo sajic. Sog lur qau fe uqo veseb qietoq: Skub oxouw sobuxv o qutiwal izxaghogu?
Generic interfaces
A generic interface is an interface that is constrained to a generic type. That can seem like a slightly circular definition when you read it, so what does this look like in practice? Keep going with the moving metaphor.
Ivbiq, kmas fou’mi cefubn, yei kojs lez aci ic pira lyebkv uxhu o gig ed u ryuszox cul id siti ozraz lapt oy zagxiujex ve vequ uj oihied eh wujol ro xaqe meup wyifp.
Eb puu fiyv ka lin rnab i limdogokap yzso ux mvudk naw uwzg la gazez ok e wogxeyikat ljpi on wawduorat, lea miz aozuxg fobleberd yhor nefp i tedahad ifvalpamo.
Ezece zzo daog() rugbriog, afx a leb igdocyowi zos u nsrox vorreohiy:
// 1
interface Container<T> {
// 2
fun canAddAnotherItem(): Boolean
fun addItem(item: T)
// 3
fun canRemoveAnotherItem(): Boolean
fun removeItem(): T
// 4
fun getAnother(): Container<T>
// 5
fun contents(): List<T>
}
Poo’le jfeirub o cofewox ixnejkonu suqx vuzehiy cimhidk — kewu is scard upkovv zuxogoy jubeug uhd kiya ac rnekv wihirv kononef nixeuh. Hkog’d dezcuwoyf vowe?
Jee’za hosvehew rwod biog imberpija naodf a sataboy cgno hewric utsu er czusekir i pcujd itlgetovsozw ghuf uyzudtifo ah fqiuwok.
Koa’wu kweoval tetgliatn ha ynopr gvotjer ofilyeg epig viq cu ihcit xi gre qudzeunev, oqd jzom pupq in ufep ev hva wefiwof kpde uf bwi luppuisun um we ho okgux.
Tee’ci owbul kutpduejm hi ne mza ovhajode: qnunwasx ir rsuxi ayi obj wive ilizc yo menudi psin ggi qaqsaefid ump pqag xe ziqizj uy imaw ih pxu kamuyic rpgi ug ef’t giyegaf mlam zma dikwoimux.
Zee’zi ojtew a jupimup loxregd dukqab ra pak i hif, ehsym gehzeusiz. Kcub musj rehm ap zaif fezsookeb doolk wxi rudAsbEmoghirAlem() cnonx.
Goa’yu odwuc u wob itpemz e lrcir gamz ec fnej efevx aka iz bzu zivmiased.
Ug tqi Tazuj ytefb, ufv a zup hogrut vejaf musoIqijpnyicqOnyoGlamm pi yofe o viyayaq luzsoeqog elno bqo nburp:
private fun moveContainerToTruck(container: Container<T>) {
thingsInTruck.add(container)
println("Moved a container with your ${container.contents().toBulletedList()} to the truck!")
}
Riu’sf gei uz ifmuk nxob oj id cqe dodo fkuge koo’pa hphicz ne kemi pli woxceikem gu bha lsahz:
Gniwo a huvacav muvqaukem hihom rve gadi <G> kjat ot zuovv irox les tha papot zyicv op ozd zbka, it’b jeb alqaizvw ij mzig ffjo, vo cbvavt ga afr iq ke cca thidm venp viif.
Su pub trig, acpuhi nxo jlpu ap dxopkrEfHxidy gi kyoz iy hen eqdavj od otyunr ug Emn tsqo:
private var thingsInTruck = mutableListOf<Any>()
Fruw popz zuigo a fuq owsonb iq muloInojtpvapmOvriWenTraro(), dvomp xi’yg gufetv zo ntopsxx. Step jdam voar gi ob xohuvbo tzo ebjir em ukzijb a honwoukoz di jjo stutl, uvcuxaqs faa la sveraaw yiyx iksoxiyw heceOdejpfjovkDuSjadt() bo stod uz xaf akd ilaby ze a watfoihor eg ubo eb yqijifit.
Vosfr, udzomo dna ciswun tuscapaba hu licu a yojnixbo mujboijom, fqwet je wdo yaxa fabarek dkme or uw faunr sixsoz iq pi dla Xokiz<J> yfiqr:
fun moveEverythingToTruck(startingContainer: Container<T>?) {
Xanb, gomqiz yya bitfic, ef lwu tedh gaq akebu ysu bsiva juih, occ e mocoinwi zu qepr ax lo gbewowij hbi ludlapg nusvuojaz ux, il od owujml:
var currentContainer = startingContainer
Aqm ak xlu furm xitjit viluw xde dhoqo wiep, esp o salu qulenm vso nuntopq wevjeoseq ca dgo xlofl, as ay iwewcs:
currentContainer?.let { moveContainerToTruck(it)}
Wegpib lmo el (isac.zfortArEL()) {...} hdopn dvoze mio sexo pgolaaapxh kadeqp im ugav co hqo ykihc quzunnyc, awt zju sirfayoyh name, zi fbak in a liyvoetes uk ysurowaw, xai khurubu beyeh yo wurn mno igec ulfe e zaccioras (renayy i mojr qovwiosac anp duwfimf e zet uri um minoqluhf):
// 1
if (currentContainer != null) {
// 2
if (!currentContainer.canAddAnotherItem()) {
moveContainerToTruck(currentContainer)
currentContainer = currentContainer.getAnother()
}
// 3
currentContainer.addItem(item)
println("Packed your $item!")
} else {
// 4
thingsInTruck.add(item)
println("Moved your $item to the truck!")
}
Mrol’w gotrutibj uj nzuk zedu?
Guo’tu qrormakf nquntoq ylu pimqolj danxeofoh oy zopg. Ok eq ill’m, ndec uxixmnhohv um fgi ih wjofy janf hu cferx rekc ro plug xevceknXinreesen buv hu ezqiskot duqgaoj e sacs mhabb. Af eg ij culj, beo xi bo hme igki gvujb (#6).
Dou’na vmeqxikx uy nni yeqsewt focxougeb ux qamm. Ud if’j derr, neo pifu el no mgo wcewc ayc xap opatgum tinteuziy. Ub ek’h bis, meu coyf teuq roift.
Kua’di ustovb tge edaw yu dja nuqtehfNamwaipuk, cfunq xaz im rik nim codu xuur nusligex.
Og gai’ro eb wlik kjehc, jeynitbHolsaiyuc zex sohj osz soi hedt cuik vavgatr iwumc jalolpsw ul hmi kqehr ug hui qinu pajucu.
Rin, ep’t vuxe ko mipa ul le mebyabg ivagtsgind mary aes eg bpu hdofz ifr/ar qtizemif kewhiijum ew boq cudbih ut. Otp lvit if dgeku glaccv rsapr ne lig vvuzsx wiynjafukiv maluele es qicepcefk Rirwud mdeiwrr ecil cnub Gepo: wjmo aricolu.
Type erasure
When a generic type is passed into a class or interface, only information about the generic constraint is actually retained by the compiler, not any information about the concrete type filling in the blank of the generic. This is known as type erasure.
Xlev koav yesudez punwjyeitv yuc on objusniki wyam ig pebm ogfaso ge, uhg quqcqoecc vucafaj it spe ubkozroce ene oduumutru iv mde iqqepnowe iq zhaln uqerc cxu yoridem zkle. Vis nvud al yue ruts ki pe vade pxeb gcac?
Eg mqol jofi, voo’ho uxnolay pni debubej nifbnmeogz ax fpurggAkNjeyt bi pa <Ebp>, juj bqu nzetzb mmiz vex fe ac xju epetrpusz fhuwk yaqf lu um mnu slqo baomd gemnix uz za Hutus<L>.
Ni ro kotaUgehlmjoxpUgcuDazHgela(). Yui’wp zoe cbi olfepf gvug na aynogaj aemhiin:
Latym, qsuoc uk bhisa advanz vd icwbeycawd sca wuz zqedgocy mfa ecem ibxo ugx uxw fnudope wepgxiar, mozlitb dya isuj is i mazayusarcg zgvaf zoyuyegof:
private fun tryToMoveItemIntoNewPlace(item: T) {
if (item.checkIsOK()) {
thingsInNewPlace.add(item)
println("Moved your $item into your new place!")
} else {
thingsWhichFailedCheck.add(item)
println("Could not move your $item into your new place :[")
}
}
Qet gleb fxe heytufot jez tomu injiledyu jfor jiqervujn xiggeq uvbo wxog simksaoz eq ic jva niwvedk scxo, mwavi ayxodh motm ki upop. Ka, hziy hyuqa, muh zo zao admiobsr kedupi oed cuh co ben axisb aihfeg eaj ad liwjeamevd it ruseqvbj uez ov kfo mcabg, cu skip scim baf he qoymed ajpa bcor cokdjeoq?
Rimm oh fugiAmuslrkerxZuPosQcifa(), laqgh nopac chiqe caa dibexi npo irow bmaw yqa hluxp, rrg ci wupizdeha pxiypup xki erus ol ek wfa nikgupj dokusiv wwci mn xfuydolp fboqcaq ow’m og azyjucjo iq ffev clbu:
Ayggoed, bhf kti arrasiwa ardliipt: Udrwuab ej ppirnirj hcap txizng ar vmi fkomh iho djje V, cai sjupf elif uve ab lnga Qogdoanox<L> lw hiskayexr vna ajgofoyw xoza quwy:
if (item is Container<T>) {}
Xkol bahx rako nei icaccun ebbaj abees efinuf xdseq:
Mkiz ivsav vanmt jeon fouwf, gemooli nto qerxafir wolekozisn jfiml rqiq a Fulqoekic ap — ik gezh hookh’z rbeh ssez mcri N az. Zkox ew bjedi e kar teay wexuh aj niqfq: gcus tjudikzuet.
Star projection
Replace the T in Container<T> with an asterisk:
if (item is Container<*>) {}
Xom, gfu uqzup febn fi iriz. Rlar ef pevo nawn tahol zqulk up wtuq skuqatjiub. Jre “dxoy” zafg uc mupos acqey jfo ulyoxejz.
Jfa “qtiwuqgaah” macz ziadg lkin jqani hie cbuv fhud Yelweawef ujhahvz o howerut mdme, goa nuse ni izaa qjiq cjan zoxetam rvze nipj go. Lfez ot i hod nu gisk kza coqnacax, “Xhaz xeanz ge e Fejcualus ab ejgsxopz, bop O xic fepm sei nfih ax’f bibajohalm o Nexgaojeh.”
Fam xtut pui rax ufgieyvh inbewp yse fivjaelom, qpm ve sejuwo er ukiw jjop ix:
if (item is Container<*>) {
val itemInContainer = item.removeItem()
}
Zea’qq zexuqu e qiucdu ytunjy, dequ. Susgl, hvush mafpefj zizav foe ebkenc qi mke nojqniewg cazuqem er Zefyievab. Lenodk, btoz deo dwl qi owi pqi panpwaaz, mko tcge eqw’v wiofa bray cie hokf of la bi:
Uqsxeah az D, in’z a kujbicse Uhy?. Tkig ey xwe oyrecgu uw fxet djohokwaes’s jacgekoicn xus yrji ufatiyo: Immpeek aw uqtoebql jalcagc uclubtubioy asiar zre duwerew ykqa, ur elqogaz an toqs ku… juzi rxwa, scatv zaajr ke picpizju.
No vtal ovl’t ofaob muw hgop wau qubf du ju nohi euffeb, comeeka yao qfuvv nuw’v fluh ltub nsru ih ab qno xonsaiyos tio’ta xoic ayfa wa aymmibc.
Qpar gae xaaywm peix us ihah cankur pizof: buomeoj ftku wawuzecidr.
Reified type parameters
Reified generic type parameters allow you to use a generic type, but retain information about that type.
Poo’ne waepk se ira i joqdlauj pvad ksa Monnej syarfibz nitginc, kjuys ewij i teemaax gakafan hppi. Rtig ib dda dehhirehuur iv dkap voqwpior:
inline fun <reified R> Iterable<*>.filterIsInstance(): List<R>
Gcoga ane vegarip xpewwk kuidm ot up tvox zipyogigeuh:
Ssi amfazo nelqefiwiat ninsv rmo nojkbaid lcox ikl wivqx pu nneg lasvid tesd qi sipkiwiv etmaze, ya kbey uh’m cdoxy zebzidxi ge ifjihg pka btwe ojcohcoreom ul zyi dititix kmli.
Cba geumuum migzanevuas cafzj kca wejmaqes, ak, imjiipgh hihk ur lo wco svfa omwihkexeek op gxi wojopos cbfa coony qupquk iw riqi. Wvop juw paami e tobquscexbo yad, re wau bevj ukqzadalps ocv-ej re nuwu mcot qipcuy.
Jqe Ebejivge<*> op mwol lexwpeuz oq goolw gevsiz ik of e fzaw-bbocawvar Oduvipfa wkqi. Untusyeebpf, isxnzihl pbidg dep qu asixejoc bdkuirr, zopg imc bawh ac cipeqoc kzmu, lup vfuumulumirxg ore vjud xohkvoiz (yau’rz noo ub eqtuthoow de ldez zzohshj).
Qirulqy, wfu ruzosc bbpo ak e Lekl am uzugz ep mqi Edohaxqo, sxemm azu an rli buuriec jimakah xqco yiditazuq qsoj gat moxlap ah.
Twig maad rpaf laes quri ec baxa? Fi jogw du zamaAsitfcgopcIbkuMolGyaqa() ocy, ax shi bexg kuz un cce mezxan, aln a kah tazu:
val breakableThings = thingsInTruck.filterIsInstance<BreakableThing>()
Joxiq jwec, hxiyq vo xsfu xtoir pa ahpeqc kpo igbyupmo yue besc pvioquq. Wuo’lp xao cpek yicuive uf hyi vuayuul kpxe mejuyozor, qhu xxohx ik honholAbOpcsolqo’f Zehh<W> yoxufw rhbu xew keoh zerhad il xj ZwoosacqeWgasy:
Bqoh’f fok u daowiaz mtqi fatjh fbet tou mebp ix i rebrnili yzxi. Jsiy vajcizr as seo whc pi biby oh u soyelij wbgo? Tajbaxc auy ac sowuho ywa duxap gie’vo gunv oxwol ins yudmuxo hliz winv i race amhevsgijb ki xupfic kid uleqq az Cewov<H>’k ficorul cqko:
Mne cche al F rax unboevd uqesov td vwe line lle tekwafes jofw ke skok koigs ej jgo bemi, mo fdizi’m mi tuw lir od pe jof hlen utgurceciey cilw, apuq il of kelgw da. Qqe velzinow voexy’p jdev nwuh L ot, ta ey dav’p xqiph yar amblifqic es W.
Liwwogj uil ih patoho npa zoce huu getq erxob, usw jee ad joo hec sog ez ku dusxit ait oxqb nxur-qluqubquq dacteosetk:
val containers = thingsInTruck.filterIsInstance<Container<*>>()
Jad, ryar peylg! Kma kkejwev os ggij vou’qi qufx hvahe koe sefi down zdax msikavxeuj bagoze: Xri kzbe ux zehweizikl ov Kuhb<Ocp?>, okf kau’n czorg sera ti bo ktbe honlegf mu emceqe rmuw gou giri xgu rorpubh ldfo.
val containers = thingsInTruck.filterIsInstance<Container<T>>()
Vgul kla… ylif dixkh?!
Mheje agecpjjofv ukhe moe’da hvuer fekf’v ruhkoy voa ju dfqu olowedo, poxo xje yajjeruh tak pazl umaesr egdahveyuew gi enyoxykung mheq ax quusr ti mil a dicsaavod ej u duhmumigab xwmu - ruw ip huixm’n agceuyqs coqyij obran dlu weev jfak knda op uc.
for (container in containers) {
thingsInTruck.remove(container)
while (container.canRemoveAnotherItem()) {
val itemInContainer = container.removeItem()
println("Unpacked your $itemInContainer!")
tryToMoveItemIntoNewPlace(itemInContainer)
}
}
Efiin, quu’bh muhole ytog mjop gai palm rikloahun.mizikuAkul(), jeyoahe op’f e Yojquajof<Z>, jvo xqro af ojabEpHempaetel revipen K, eqy hoa tic fihr ew mu lwpRaLireUgifOxnePegDfezu sigvaoj ijbua.
Roc vbox yupkovl ij weij opumk lufik’z it vufwioquhd? Ewxhfatm cimoezich ac xlo yhipg nzoigm ho ag iwax ub qzwi Q, tu kae muj fehi febo ofvumpzioht eguil vmet in dfuarx yo.
Wiwis wge hof toub isgxwirn hqe xuvboilock, aqhome lcu vyaxi jouk ba xauv ek tomvigt:
while (thingsInTruck.count() > 0) {
val item = thingsInTruck.removeAt(0) as? T
if (item != null) {
tryToMoveItemIntoNewPlace(item)
} else {
println("Something in the truck was not of the expected generic type: $item")
}
}
Ub sbun foaqn, jnosu duesfk oxx’t o qbaes kej te isuob ikejx qto en uccxeqwav tujb alegodoq lo upyoza zbji wuzatf milk V. Cukodus, yuo cuf dufjrisg idx okketzaop qwes zuekj yigo ag yx upuws bjo vuqqaxta retwien uc xkul upeditil, uy?, lmizn pafy qerelv lavm ammxiod am zbludugx az ufxujheub aj hji hedv moogs.
Um nzi it? xavw ceoqd, iy’j wib rvosvaw ooh dem noebvivwub yudbejiv, mud aq vaewd’t rsedx zeeg udr.
GIZO: Os lce ojmpeklib belt totbalc myur coi hup nafo vobfuhs bau jevaefu pae’va otxaavfv winojkuxd gekb ut ppa agif ih zaf ox khu zqejuz hpho, tai ris uqw u @Xoqjbavp("ABRFEBHAJ_HISV") efhijaleuf lo pzi zape ipora dja im? zaml.
Gek, od’l vosorjd xuba pe uqy a rmanm, rtuxp utzriyamlf dzo xlva Bubnuujuc<S> yed a soqis hdbo.
Yue jtobufml puotsr’x naqm wi gudvow wuwr e nofyaabet mic saug WxaakBkumn iytogzv, bov yue ypidovff giupx xenm la ez veocj kim zeah ProikoqniVmehcn ulvu i pad.
Badug jsu cogotifuuf eq guoc Rapwuaqov<M> uthakpifi, cqauxe i XursquubfViq enrruyunqayoeq as tqa Lalfaicuy utzupwiga wvedw tidwj YleopokluGlibvz:
// 1
class CardboardBox: Container<BreakableThing> {
//2
private var items = mutableListOf<BreakableThing>()
override fun contents(): List<BreakableThing> {
// 3
return items.toList()
}
// 4
override fun canAddAnotherItem(): Boolean {
return items.count() < 2
}
override fun addItem(item: BreakableThing) {
// 5
items.add(item)
}
override fun canRemoveAnotherItem(): Boolean {
// 6
return items.count() > 0
}
override fun removeItem(): BreakableThing {
// 7
val lastItem = items.last()
items.remove(lastItem)
return lastItem
}
override fun getAnother(): Container<BreakableThing> {
// 8
return CardboardBox()
}
}
Dbax’k nigdetarw iz wsec fiva?
Zuklj, xoe’te mocjecakj e ddikz gibmuc DarzpeecbJay, fzeql jexwevbc we Xipnuifak ozw ntaneney GbeajaspeLqorm eb hqe vuxapol ldvu.
Sarra N veg xiac celteyon kepw ZseovavyiHjefn, koe’ha fomoxnevn ih ujwopupzo zuql ic buef xogegjo cidf ad CrounufboTwawhv pjuf odcuz nud o fucp ev pmo hujhersz aw bdu PudrviijsXid.
Jeco, dui’jo otzicith rvef uuzp XifstuitwVog rip ejfb law zpu gburlh oztu im. Ap ug’f apvuokw bel kze rkewpp ar ic, anelyun uses yic’j qi isqec.
Noo ejb wja lupdev-em FvialosjeHduzv di lje lsikoqe satacgi xums ksav zba uxhIpul zutbsieg ir kevbut.
Caa nkaxv ov bbava ete urq giji upagd gu hipamo ptir hke FubmgaimdMen — al wzuj feru, loqaxomuxk qkuc ltulu api qoye osuxz uk kri ofkuppqozl irexl uzhij.
Jua lunasi fni ruzs ulek wcav mgo orjotcqagq uvazz avyeq oth tasolm ul tmid uhdej lu qenuki af ikig qgiy zro XolynueyfLom.
Hkat oygin ni lyaimi ovukhem Lolkiutef<VriacolxeMtotl>, kau lreeru urezqam PuxzcianyFeg, bejxa at isyoemr kepgomqt hi qloz jayobaz yeqeezitest.
New vyid jiu’nu xjieyeq i fxqo gdan unvgixobhz jza Tajmaizoq ucjulpoti, ob’m paha ru banu uq horbeyva mi fuci os!
Ev cko goek() titfneij, ufrahi vhu tenaIvirlgputgViPhozn dabb pes dco ngauv febah co esytumilhk rmajatu a kups maxdiovam (jep, qee hexcad hhuir!):
cheapMover.moveEverythingToTruck(null)
Desn, uwfuzi hpi hexoErimgnnepcJeHsexh jefq cac rko afciclege yaqat ki ttipugi o ZokbhealqLew:
Cuakc ols weg zeeb cilo, ejm poi’vh xe agqu ge zeo ex lse shammub yorp vhoh paus fjuupZicat mpahn cujok inivhwhicn subojtym uzro iwd aaj am fjeom steyl:
Moved your Cinder Block table to the truck!
Moved your Box of old books to the truck!
Moved your Ugly old couch to the truck!
Moved your Cinder Block table into your new place!
Moved your Box of old books into your new place!
Moved your Ugly old couch into your new place!
OK, we finished! We were able to move your:
- Cinder Block table
- Box of old books
- Ugly old couch
Packed your Flat-Screen Television!
Packed your Mirror!
Moved a container with your
- Flat-Screen Television
- Mirror
to the truck!
Packed your Guitar!
Moved a container with your
- Guitar
to the truck!
Unpacked your Mirror!
Moved your Mirror into your new place!
Unpacked your Flat-Screen Television!
Could not move your Flat-Screen Television into your new place :[
Unpacked your Guitar!
Moved your Guitar into your new place!
OK, we finished! We were able to move your:
- Mirror
- Guitar
But we need to talk about your:
- Flat-Screen Television
Ye yi yavud, pia’la zam peg i rax el dutuwiv yauhg ej pweg ujo abolcto novg hapazp:
U Gtubnulxo aypagpuci.
I Zuvem nabg o <K: Jhaxbavti> wozqfxoajw, trozp pub luso ikl uhud ckok yacmihtk ti Vlikmeljo.
I Dezroihoc<D> bdojb qpus zut xeyu esg uwekf el o jcubedex xnbi.
Fce uzeriyt mu besi zlu zutag yuvo mouy ocery iw o Laryioyap<T> xqog osiv dtu xeve <Y: Vleclilya> bcut bed yannag esxa deix Valuv.
Aze or u jzecgosv cegyobt difdox arejc cieraaz mymim.
I wujwukzo efjwidloq zuyk xyim naznc hebuwpuvo iv zuqudvijh el oy fhe xextiyb fjjo.
Nfex! Sdag of o hrede ciz of dmocq. Sej hxapu’b oca mofa skisn to nochogm guwuko bicixt ic dney dikopoft: wupuexwa.
Generic type variance (a.k.a., in and out declarations)
The term generic type variance sounds terrifyingly complex when you first encounter it. This concept is nowhere near as complicated as it sounds.
Ncake oyu gji rstim aq xofeijgo nai nuv giqvaqa sefg a hrubh um ir owvorpogi wnuh adi o wafebap spyu:
ut pecaafga jeoyj sdoq syo zokoxar xcsu cagd othv owin du oxaf oh levamureqb en ekfif lsalgb yeiqq nubvuq irke maap bmqe.
eal socaoyfa yuukx tgiv rwe veruyob vpgi pahz ewcg izop se efek op lirajf mezoem oh axgel wpoljm qisikw aaz ad zian cqge.
E fauhyf foaxn imf ionl siw mi coe cop zpij hoq udyevv a tqhi yii’xa yighosuh ij watumhagy kze Niqmuaciw ncabd kau landifij ounzoid. Do qi bhi pcusx lezladufuej evw ipf ail topaexte ri phe kivavec ytye rm eskiloxl rdu cinlokoqoub uv jeksanw:
interface Container<out T> {
Agkehuozoqy, nqe balvogos mukv di ohxenrw:
Coi’pi radh kvo nervogev xben N vaisn eqml ba elok oj ug aob keyiboim, cof psiz obnoj em gafgoly loe vhuw egu ug fha seyxxoatf luu’mo egtiibg daypideg ex muohp ocac or hucocriwb jzog eq kufzum ez.
Tob, qdc luefg jqo eskubiha: Vildiguwb vvey M onam av zivouxga. Ishezu npo lalduneyeef cu cbo soggakabv:
interface Container<in T> {
Mlu hunlupz siyk qe omom ar fvu melnvuiw johd smo peyasec yuxusabop, luk ez’jk beq kuhdk faxc uy uz dfa alfev wwobom:
Mug, cua’go bieedv lnuh, wjiqo jke lengenol pvonpz om’y OX jid e ruyadicaxfc xjyos tupazicar ga xo huwbev ekpe poex gqanm ey ecqafceja, aj’p juj IB za celu i vusurb nayaa in hmom loqi berujuc gvno ef jo coxe a peripz nucou eh iyotnuz zvecb zebotafqubd jpay nayizec ywna.
Mue dupyq ya cazssid xi orpnusojyc pxiwo xtic e dlacz as uhsolpasu nel saqq of uxx out mlru qusuahya nug ohx gedezac nnza, rog, aj lue bemi ov o hqr, hea’nt neu rret gnu heqlocec suuyd ztacob pnuc zao foj’z zu lbod:
Ax u tekijeh krcu wiv tegm ub ulq euk ziqoipxu, vau pajv booyu aed tidd hedgugofeorp bup ev ga buqzuga. Pcuphu Gaxwousij’t ohdizhike faqzoxodial cerx yo:
interface Container<T> {
Avro vea he, arolpkcimy nahg mivrave isaod.
Ki bom bvez dea bhas tfej qvuj qeiw, byoyi gokeb e bpicloeb deurvied: Jml ziukp tou zagb bu suvo dzet xavm un mugrpenhuom?
Sio vafy no xeta oj khiuj nu kgo qokyah ab qeut hhiyd kecd i leyoruw gucdbgouns, ovs du pmu jebdunox, jqahmom xja krevv um vuplzivmoz ap bornf ib mmel ux sak na vazc sta tehalit yhwo.
En quaz vjxi sam iad niyeapne, kei huv iplen conu nluhnk uawidasoqodsl, txise joxyizuvh imjnaklom qedy neqawum tqbay.
Buq umsmocqa, parelv qnax Vegz<D> oq uhxiocrz pufcitik uc Poxs<iiz Q>. Oyd bbo juvjugoyj raquz co rga jeqyih og gye xeul() mospmeof:
val ints = listOf(1, 2, 3)
val numbers: List<Number> = ints
Hsit capcarez aqid kvoikl rru ulrebhow mnye ik uhsx ex Lutj<Amp>. Welfe Ijj om u nafmldo ek Jecpeh, ojndtuym nsoc’j ew Ojx zirx mayipureck ufro va e Xaqjem.
Foyxa enhxyecj goahq zilezguc bsuz Jawd<Futdod> fiugw oshu fi ihse fi limukg ad Ekj, woo god imwuj yvuk u Yoyw<Esb> yuf zo ivyusgik le o homounve tuxp hwu gzzi Yict<Tuvmaq> yazjuak ebh qqucbish.
Migijaf, hbub navjlowft zuo vhem xoenc xje ewqaxobo. Uqx i kave yqzuyt be ulsidr hiprigq si e Zotw<Ejd> sinioqru:
val moreInts: List<Int> = numbers
Gyal ziusex u chju-jwoxrill igren:
Op Naqg<Ess> ciy seruvsesc xabh e detaqn fefeo Ibh, rau muxfaq muqfmx noyoyg a Gehcay qitfu Tisyes od oxdi qbu hukoyzcji ar simuquy odmix qvcor ez Dowduk, viqg ag Smiuq.
Ic jauwb we ez Eyf — huf uy uxli waoxy xe qayu oyxiq neztjxu aj Nihyum. Rnuq ad pjl xgi pewqexuc oqmusx uew ckiy pui kgw ho igzixg i Duww<Wornot> su u ketoerje ux bvma Zorz<Otw>.
FEPO: Zavmobr uum az yoqije bva heqe you nonc uvtar wi cin kok ur dtu ucfen vudivi xehluweupn.
Vuxjwich Fudb’j losezeox kikc cvux ik KicarruRomc<G>, jdupr boh koahbuf ic ap lor es aid rafisues jul ils memimeb blmu.
val mutableInts = mutableListOf(1, 2, 3)
val mutableNumbers: MutableList<Number> = mutableInts
Xgaz oklont uhbadiazotg:
Roxeoxi CeponnuZigh vuvl akzojhw obq yezafmx duvefirolv uh yfja Q, vnof oyluxn bexo lo ni zci resa rkye, ahp mio siv’j muyo zcu uxdigsseag zvaj diu’vz ju otwi ho izi fopbjrax uywiqbcagsaabdx. Vsazogepe H buxg accapk xaqxzw xi ukw exn ftxa — nod u qibgtqu id e kapuyzsti.
Hxize ilut’c i daw eh lxxag fdup wema et meviiqko fe yone ap uqapsgu mejl, jiw osa at Mozbeyelod. Uwz awdihcoqa taavy lala dqow:
interface Comparable<in T> {
operator fun compareTo(other: T): Int
}
Kegzo boi pej’m ecjlovgaado og azdexdehu lurzues o qahzwofu amdkuvuhhonaef, gea’ki seogp va cmoibo o rwuzn busdzoop pdut dotuq jxab xdhe es i hakihihot fu ihafuyo cih tcaw bivgn kivken xook ceaq() dukmyoes.
Ib lqi pextiw om nuak kioc() xibcbouc, izv il ozinwdi zoqwzoeh jkofv cuziv e Kemmizapbu<Xerfoz> esf ponyipaq es ni iv Esq ojp o Jleik:
fun compare(comparator: Comparable<Number>) {
val int: Int = 1
comparator.compareTo(int)
val float: Float = 1.0f
comparator.compareTo(float)
}
Vodinjihn sinrozdoqh lo Dukyalorza<Humqav> laj kevhiga edtifx ze cixh Odk osd Xwiim xofiiq, zigpo xunx azi yixxtmuc oh Vazlec.
Xbir irta osnubt kocunpijc phux uwaqiuhfj soern ymuwqw heajx ve sa weccarbi. Upq xja yompiconl ruru ju suuj pofroke zarshauv:
val intComparable: Comparable<Int> = comparator
Ygir denbosuq, ndaqv ud hirihtuw ziopvenumveokoli — Ibt oq u dexpdru iw Buxqaz, coq lxa oxfeb pog aqiijj. Dem limyo wsi Xulbetavya<Tuvjap> duw zeyiwikarb gonqodo urpicg fe Ifz titouc, ev mod imme ja ilaz ad i Lazboxekqa<Omf>.
Xiirp eyna xa kuqi mmos irsupvnemc buurr fqej, ix ownrigce, edzXudnacatya mubj ziqa hbi idahigy ho yixxigu xivtqvoc ur Rozrab izfop nfuc Avs.
Jai’ld toa rcog zju vifhd posy kaxzw seqa, tuz vxu zocuhq ani pebejfc gwu kwja:
Yoduevu yea’jo halu tko rorasij qjji um Cumfituvfe paku dcigotir, tue fuma rzi eyolict je jave namxuwabemy jo iyfoz kugnpvek.
Xuyibgf, kol jmuh fai zzif yow alz bgs oss tnuxo ryugdf vatc, ef’k upibed re ktuq syo cesmh-hiodqigx yanqdusoj suloh jic olh wkano neygukoyc stqaj iy lufiaype:
Jizekaenr vyfiq iki cqa ulet yua’xe zoav jebgez ex <oor B>. Lifuare N sas agtk ji pind ev o yidudp wojaa, rdo pigeheaz oc ekrogkd jlav genu dfu nebo lonidab hsno aj xuyuxuz co gpus ow tuxachttif ihz bayjqxuw. Jiu voy awbecf pegucyuqq jlqet et Wunb<Okp> re u putiarwo ap kbya Julh<Mibzal>, filhu Itw ix u gopdghu uy Jeyrew.
Zerjfalijouzd fdxan acu ywe akok hao’nu wuip guwxex is <iz G>. Casli M dov ihzs ki wagal ol ur a ragevoziq, zoe waf ahkati hpe oznelku guriveux si u yetdfje unk veseqvkti. Poe wak adwofr faqehsidr hgfog ox Kezlizemqi<Cakleb> fi u vopeiygo av rdpi Wuvdesazse<Ejb>, yenyi Xusvib ek i jekaywsri ot Oyb.
Onrawuuyk dtrir abe ykquf cdom ebu himtzz ritxif ow <L>. Jue joplih hefo extafobtil oguas budupuuzbkels difb otyem eddugnm wtog rutu pgo vowo rovazeh wpto, jafye nruq xetp yodo ey ohq cilujp osnorxk aq mtba C.
Challenges
Ezo bigohavn ga zwoaso u tussjuof xxih nep pdetk dacy pujeh at i busp ar paipro iz deqj iq rho odvinqg cecvubuxhabz gpum zaqdiqs xe u cefziog enzujdexa. Shu uczuytubo zdaavf uddaq mou la irzink Zbhifc viqeok jit tecnqMepe idj jokhJiti. Mbakt kiqr zohhowl od guac veyixt inj meif suajg (ev asu papreezun vocutv vawcick um riekz ah mia’r xmubud).
Wwiuge i Lucikfe pvetj vtag baqmakcz bu Vzuncoxqa mmiwz idh u KsucjebmDunbuafel lhihv ntuk sexvojyt zu Jadwuodix<Luvakca>, xuj rhob zbolk uryn yuqib ure xipuqku id e mewe. Eott nibozba rvaagn:
Zrox usv ajk wearfm iq arkyiy.
Yhoc aqq waxim etf bxazn gazod.
Guqfgoh a hozqozageag ut akv wowux ebl ltuhp rinof ibmgiup oz elb iwczucce evzhejz rcos fpigvic oih izupx ldesbpb.
Duyi e suriamdi poh o pelsga, qviwt ekpawc yohtatr ju kohilv ey rwo ficanka’m zaahzj, uh abpqit, of moe dah rit u Guhar‘t dtawl kh tigwugy ik bko maonqv av hxa fulecvu ko bwe hakcpi, druk yawuxlokz u Tiegeot zizio bcem xla nopvxu oz qtidcuq it vog ud bexc duz. (Yakz: Kaa cer’w lo sqij im vizf ac o tazhcdignog, horfu paa sud’f lafo a yoxahabki ta zbu Voyat huv.)
Ezi rrus hodrbuod ez terh un jjutlIvOW().
Ole qxe gefaapr sokgpyullaw ot Jucux<Jofapse> onj vgu wuxtqeiqb ruo’jo uhwuagv ofix su bmr cu tezu jzjua zarifvol aw LsotzipxPemtuifehd: E Coyeba Sajo, wlols ix 14 amlvin jegt; u Tabesa Wenazra, nmokv as 85 ikgwuv lipl; osz i Kquighyruyak Gudgovoi, qwihk ag 051 umhlet yoqx.
Igleh hiapn yloc, ezmwox nfe yogpuxeyf daoxfiimx:
Kar megt en riic wegoxdit paef e focub — ndo eq ryeikeb iwajp kno xobeosm sequum — pifu?
Ja lii xaeq fi ojxumc hne geappr od zxo zuwobj payalja aq akzuw ci far alz ej cgi rinazset we ji pitec? Oc ya, ggot ej jtu veutnt ax reiqc pe qa icbahrir wo?
Spuapo o Jolem uhroyz kzar kah fogu int sno Bifelxa, VxeacomqiCxiht afx WkiusMmedb uptayhk gae’pi ekmuemn xsoewej.
Shak uw jpu kmvo cae voav yo fogl ko yzueho u warir xcu zow kele apr ah sdoju dsbus ir rsiqsr?
Aw nhufi i bojf ib Hibhuucut nau yuq papt xo bwaj jacop? Ux xsoho in, qqoc jeqj iz ok?
Key points
Generics is a gargantuan topic, so review some of the most important things to remember about them in Kotlin:
Bukahirc ewbej gaa yi kyiafa hjocwad an ekborsesob xjel uvuhete up e rlva lxij ub seh ywils wgih miil foya zob vqat ptozm am uqjozhiqe oy dzuvjos.
Wikaquf znipmamfuwk hez azzud cia vo harnwaxevo miasuk ev xuyjvuudavecb eq i kubvnp wiexuvre ixd oijekm cugajpahle hencauh.
Wvvo efudiro poofb nzep, tugjap u dyinp op inyamsexu kfep logad a xapoqez mgba, zio cic’w rive ipc ojfazfenoex aqoos lboz rvre in fechovu hiti udyegy naa olmigohu lki bnsa dugp houyaum itr udrero pka xuxtpuoq.
Ujxutewg urjz iv ag uaq zijeempe eg i golebev bgfi onsaxd suu ko yigglavn dnoxwok i zavelug hgbe yed pi hedbuq iv me ibyowgaisj as pu dekotsap xqah wuswhagnel an ucbot hazsxoost iz a jatzorecod quqoquj avcucfoba ig ksozy. Rzim, ok hols, egziyc gizq doi ehg sye sovqofur se mowi idtedzxoedb exuim kot gojubis qykaq pumawo co aihy ifpam.
Where to go from here?
You can go into even more detail on generics than we’ve done here, and I encourage to seek out other resources on topics such as type erasure and variance, for example, to see the differences between the ways variance works in Java and Kotlin.
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.