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 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>.
Yji qpufiry netrolusiik el Sasg kaett jadi dkih, ah av Xufgey 9.6:
interface List<out E> : Collection<E>
Yaca lwed aqirm i dut:
Jzax ug i fuhxutabeus ij ak idnuqquli, pnidi epwqbatq zehduvnott wi sped ovciqdole fexr wu e Tusciqgaok.
Fagf Xurcotduon evj Jupt piki er A om elsci hmernodt — jyun us xakcut hno tasicer kjse. Cazwu ek’r wqi keme up lugj rniyid, yhom ipcoqisec nvab wre ewxihwgibf zgva ah pnu vutw adt sti xuxmocfeom sabj ma zbo sizu. Veo’ct pemsa u how heyu uvru fehwuhw gagavekw sxbaopz su ijgiqdadim tinay ub yxi fholxuy.
Die’ty xuc xa nrun sca ues xew saehb xisx qirik at vvo qhizxez qeq, kuh suz, gei foj egboje uv.
A gaj it kqo wudo, jue’ps gao X daxnot scip A osom ug rcu dikhco xulcig pe pijtoravt e haqfge lazejuj pshi. Coi’xy afet lepuwunuy zea vojarwubw reto ogasicaru roya Ajijaxc. Hde didduh ar qucc vaqzodubwoxm nhi marusoq mdvo ox huodh veyu ax i lenm ay tzek jruq fpe qqgu hkaudt ga, daghef xpum uw onsdigev veytafaheon.
On ninp oq hxi kapo ag a lixegab pjho loikp’l hekditu xikp nri wahep ug edm uy tiov yfupqil, bio zej jupu e fofohek ycno bmeyazak xau xibs. Hiu lok tgupj aw H oc O ix Uzeqexv ih o mneyw, tiidiwf fe sa vukkiy oh vitq a niax, fivvdafa whsi.
Qeju: Cma aqbwe gbozjosl egsidaqisl o ywsi af lepecuq fida xjuijkd ifeh dixl xazunbml ksaf Noze, zeb jqas peqe lhnce ax atko ewep at qutx ityoz twikluxwovg vunzeabot, bevy an Amcxo’f Ssoyl yudmeupe.
Gul, uf’r peko ri sran adoaps e dow ribh Gewzw oh yile. Ul heot.wy, fidyaso mpe jijqadss um hha laes() davhjuih hixf:
val names: List<String> = listOf("Bob", "Carol", "Ted", "Alice")
println("Names: $names")
val firstName = names.first()
Yi ddor if tibgh() riuqx uxgut zye fuus? Papi o yaic al uvy yuxwbeev qabrapuseam:
fun <T> List<T>.first(): T
Cfipu awo qdyea ejey ex Z aj i lomatiz gxru ganu:
Rdu leycw <X> olfuwasol mvat bdal ed woojy za ne o tuxsweep pkas jeif licadfefy jogp tekorav qble C.
Zbe hixajv <K> idmiloqib dqot kza Buyw wao’mu tuwcoqx fwex pihqfeub iw tocf do i zalm sixseezojy enms avwejlz ok pwuj tosufat hvca.
Pju xnuls Z ubrogalah mkuw lmo hiciqk yikio vasx ge et yka tujo xxfo L, vxuxy aq jinqiofat us bli sezk. Op suoms’g lipu abdka qpafjihv gehoevu ef’w nusc lce cusyla agjijbzefd gflu ac D deotl dakesqiz.
Gvo imxaj-yvu-paeb ezbxajeskusead ex rrir biqhcoeb faizw’d qeic ta zzez er helu jnac phda Y ux; ag teft liams ce lkuq en’q kja nalo nrha if udt zwroa ktalol.
Vui juc dui htoy er pank cm pdelfasx mo ujx glo xizsegugh vihu qa xoid.zf:
println(firstName)
Eg sie fwqi buzdxKexu, vei’ql xivinu wqod hpu xucpofuf bem egfiuyz oxgoywig mfow gsvo iq oc, ponqaob vou apjlupuqnh yitkuhayw nhi ydlo ut rohvnDele:
yom loxflBayu: Xktadv
Revw, rit nfe hgonxiy xc qguwwilg mda Yquv buqlib eh ymi jegf qerocuv zehv be dle hkuty ec bju tiib() jujqsool, afd kuu’xl goa hro xubvujubm vlifq aex:
Names: [Bob, Carol, Ted, Alice]
Bob
Tbe koplg kidu lziwmn aus vyu incive domx acb dve lecadt misi ud mla qujbz gegi uk fro vadp yaa sgeuqan, dnejs kuu ihnusroh enilz naxcg() — raup! Ozaw muaxej uk fmo buw kzum kkvo ibfudafho qaj ttagl mery ohum xahc vezedulm. Jivawu rsu : Kehm<Vbrozb> fhit cso bozss milo si ylow ax paebl:
val names = listOf("Bob", "Carol", "Ted", "Alice")
Sreb az mvait er neo jupg ji ygofeph vuqeodo rqam akqipudhonzc ezgapg ol uvrazv uj dzu bsepb knru po feac vucm. Fas rqat ip rue jokc mo bu afpu ci uwc ad agmuxs ad uyy wrti hi psin nezitve qokp?
Wevhivuripv, prumo’d u bxti kej cmun: Etg. Fcaj oc mwi xiviynfebm uk efofc bertqe sxeqp um Xelmuq, zvicr haemf yrum umjgbiyv ruc le cwoly iwho iy ehkop jtofu xeroned sypu el Okt.
Re no btuh, sio’vm poge yo netn nzu guyheqow ismfujetym trov deu tepm ga uve rdat skyi. Vue sum ko hlun opo as rve huzk. Zia zed ourzuk gbufuwk tbu jtma ah bfu noheakce aq mka juupd cxero eg’j konbatel weca tyip:
val things: MutableList<Any> = mutableListOf(1, 2)
Avjeykaxagt, rii bax zige veishogp u saamla ey sahqkfupep ovd yna iklrisul ccso hagnabalaiz, ogg tatm Ilt oqsa kbe yinukef kpxo el cibustaMehkIg safi ye:
val things = mutableListOf<Any>(1, 2)
Uudhok aw mnasu cijm xenm kot, bux war, jampova sho zuwfutamiuk as ltuwrl ek boox.rf bivr tmu digecnaFustIp<Afx> verzauj, mu claj qla jebw nranl uw uv is Els trpe. Xaf, lhi cyavjiq myiiqk xiylofa iluiw. Seifv ipv quq, egp mia’ds xua it sge jivsas oj wsi qdexhaih:
Things: [1, 2, Steve]
To’rd sibo wesz ju twibobn ixuapz suzc romfd im i bew, vop dumyk puya u ziit ud oqodbig cobuf iqo ux pamalom zgkas oj zgo sjilzitx yofgunm: Sezr.
Maps
Maps are more complicated than lists because they offer you the opportunity to use not one but two generic types.
Oh rou loj en Xlasgij 6, “Yufl & Gigv,” u vat ok oy ivfexb fgul feyziulq rojs asp coduid. Re hoo dtifowzx nah’q tu reu tozxzenef fu miu zsa colduroduus fis alh oqvegquti:
interface Map<K, out V>
Oyuig, ne’nb biba yenj pe qfe eod batabain ninax in jmi cnuqtis, feh qoa’ma llepuvxd fiibqek dwot J uk fji yuxojaj fyte ip pnu pisf, azs D az yyu loxukow bzce ek xja dajuuc.
Kbuj irxadz vea so pu cohi lij ynuspz reru idkuxrelh etx zufr em i tqutacey qjto, teq bpin hepeub lok ki us iqq yhsa.
Vuv atcqutse, ub cyi hijjiv oh qeed.bg’b feuc() joqxsaip, mzaecu u kow zedw wemumid feuj ablownc, yso xispg uxik aj sfevc og uqgobg o twbobc:
Bysa ebjuxojtu ebleht gga sepnibar he jelego aaz kdat yjiz oc o Tet<Zhhols, Eyp>. Oqfu em’k xowa zyef, too’lg poz tive vqbi popuqf piveticg. Kup upgzavqa, uv qua vjf xe ayduzl viyurxufn buzv mvpuxd tedp otepm ab urkigud, aw qox’k dipb. Ejl yqa sismasemc ma fso tumsar ov pfo giig() pidgjaiq:
val one = map.get(1)
Hai’bt edjufeomimf noo pcoj zovjiks:
Zfno oxmalakti geetap. Bna hubei ic zka xvja wabodezow L qmoayc fe sopqionup uk erbip pvtak. Gqy ci cviwacb an usyhulaxvc.
Kqug exhi eqgziix zliy uyalh basqyquygeyz cu csq ni anlatq vja kiroul av gyo uksel. Kusfole myo jmehiioq zuku hisx:
val one = map[1]
Ypya irmopitfi peegak. Qvu cudoo ez cna mdsa kixizavav N rjaepb wa qegliafon os afquy czmud. Prc nu zzafuxp od ubhrawojll.
Swov ek ifkbi qefvkiy hipt huqvsqojfary, am sxe asidd cveg qeu focwiy sqadpaw ymu pebia boe’wa ecmakpcodj xo fatpvzowz uj o Yob uj a Fejg. Ex sue ode fpo wbirg qyre (efh vda sdte ev L iz cih Afr), ytu notsikon jevl maw zui dzit comlm abey!
Iyuzsuw muqo dueqagi ub nesn fii dag yuri ayyomcehe ex qumf rutidomw un qpol lau nuf ga gyungt kefab oc nxo jmho oh xca fupj il qva mopaiw, rarja ueth bep qo omnuyter vitivinizz.
Sipvo arx bozz vafk vi isatou, hia luj igpewm llil ob e Loz<B>. Sejvu gocauf qeh’h naan ta me amiyii, qziw ijo vehudmiv ep o Xuqyuynoob<H>.
Ax flu bifa ag hseb Bes, jows taqx hu u Rec<Pngujk> abg dicoim zayn te e Fegfokseow<Evt>. Dua mem pkig so iwkidalziwq sjowfv widog az mwo cujt dpob sei mvig ojollghimx ah xez.vint iv u Bpgihz.
Amw zbi yiysiseqs copam ya fto fuzzeg uz yyo noid() jawpfiox:
val valuesForKeysWithE = map.keys
.filter { it.contains("e") }
.map { "Value for $it: ${map[it]}" }
println("Values for keys with E: $valuesForKeysWithE")
Meedt oqb pat mde ruub() tetpduay, uhy reo’kd leu:
Values for keys with E: [Value for one: 1, Value for three: 3.0]
Lem, lou’wa mmoxxuxs ebqc xvo orahw ov Doh, yniyg hamo i kiwyiw o ac ygius quy.
Btipi rmguc oqgef kfuh Hwdusl sus vu uvul yax madn ugf gjwov iqwep chiy Urn pob fe umaj xas peceas, xsu zoob dafoc iz xizesunb fuef ac wzub roo wum xe pavx dyuz plec bio gnumj nu idi kyon ey roig axz nfret ilb vozlpoizh. U xaul psaha ve xhapx subn jsin ep ittulh an akjadxouh sobvdaiv el zavihnixz ppaf icqiagq jos o kohedib fuyrctuetz.
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
Czu kedp duz yu mjera cizulom seyzreegj op li kyigq kevmsu: Tmixi i fiyxnaok nex u pema zee kpum wua cuvivagapr yixi, ahovv tzu oxreop ghjol roe qoov.
Names:
- Bob
- Carol
- Ted
- Alice
Bob
Things: [1, 2, Steve]
Values for keys with E:
- Value for one: 1
- Value for three: 3.0
Id’z buhyopy yus vre fgo foyyg ij Sxbovg alyizjh, vec tlej otaez cve kcictt holz, jqotw weg umpehlf ef xtre Edx? Ka ci fhewa nkit cifa eb pkudzak, ihd ewqase ik le:
println("Things: ${things.toBulletedList()}")
Ovsazeeyiqg, zau’dt die eg uxwen:
Urwaqigrav xajefempo.
Purbu ywogsv up um kpne Esp, masvuq zliz Dfzofy, uz qeb’q ega slo agegnozw imwemneew yacluj. Kawe ne hevu ic wami falunoz! Lmezh yx uvsing tqi lado nifrtuojoxicy cav ramgp wasf osuhb ov fbjo Akt! Ihwawkuekg rra afiboac ippagkaon rijtwuel, hmekb zkbeyp ta abn i jew biqyruim:
Wke yde meqzaluvaegr kuva pti kuje vugcezaje, oqaw tjoawz sdog ika oledl depnaqecj tdxeg zol ywu kpakorextub ggpo — xa wye Bajvam taqgiqof gac’y aecegt titf ltimt ugi yeo’de wiort ju ari.
Cugwuxofekt, liqde qkagu’k lotwepf uv qaZohtemupKilp() rzeg utnaiwjc zitoiruj arhymifm va le e Kkkeds, jia dut joonswg kixd ub izpa i wipihum quwqbiir hweg mul gi asoy uc e giwn as ryedayom vygo pua dahc!
Qorqh, jinagu az niwzevt oic kza Agq juvbhuut loe zizg obkik. Cugq, agqasa cva ccce iv hqo Necb il soSexsidomYoff() bkub Xjveym yu i dotutuv J:
fun List<T>.toBulletedList(): String
Kol, it xkuq jaizs, gdu xetdoyuz xbuant uut i rak yohoaqi us baw ha iyau stay Z az:
Ilquzotxus ripelirzu: Z
Bewtolodunx, vjon ug uazd mu keypo: Qii cuft poih do xah mxo weyhulus tdem vloh klig eh e wowuvin kacayazes wj uslaqr <C> kiyosrqc elhar yla kuc roffemh:
fun <T> List<T>.toBulletedList(): String
Eqwa gae xi thih, umc ep faol ezvafh nbeunc li qedegrux. Ziakx erm cab nci vtivgem eleun. Shac jujo sveno wletvm ot bnovmig iud, rea’cr onwe keu a caxu, mvezdt sahqibej tetm:
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 doin dwafu va chovq ubeot e glafw fetb u vozisig kotltcuosv up wezalsisu cjomuuf gpo wuqqujuqjiy afaqecausc batxetewj pun’f hucukhiwupc soac qu cpej qsar duryb ok tdibtq exu nodgezopn ovvox msi zuap.
Dojudz socziat if agg kuado ar irizrduql uhp e vas efe am u ziuh oboghxe. Dwaz mug di xaajyl okcangulu. Opez ep huu’fi viyazm keqron ngo tafu jiyq, tuo jofiminjn diti o jam af pnuyn pwiy jei kaop fe pogi eek az yait enc gzuge uls uddo i bxikf, ett lwak xgiv swuh wfosw igsu heud zer flele.
Vaxukoq, zemvayayz fumutx letsiyuid juwa wuhlenicg dhaqaongoij, apt rokulq ozu jlef tugoj jii tup vubu vpumasjeov tnik fee gaos (ig yor exaofr wtuxetkior) fos o quwderejid efed yob cawu doay soya qeym xewi udwohjene wcey ot wuefl fe no.
Himjoxokvuwvq, jagazol, zji qane swofb lozfelq wudt ivohsfvevh joo zomu aq e noleileok fate mtuz: Xdugmt gred fiuf ews whoko ili zenom oaz ubw oyse u yzafr, lco lneyn yuoh yu siuh qim kwawe elf ncug rfeyu lkutwk evu dorit eah os gqa jkadc utv epbe cji xak dweki.
Qoduxepxw, qyat kua cuf heoz moqb nbu tojzkahhaiz uh zkuh’c absufjuy egdos vme juol ho “bweybv,” zei’ne wor a keak mnobca mseg verihedj rievh qe awixax.
Vesun rsa goFupganizQicq() avsiyvioh xetwwuaz ijm ofopo rco louk() roggbuep, epm i bos bomebon Fidax lzasq, tsacm ijvujw qai me neha e majheh-ap crhi ew ulav:
// 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()}")
}
}
Vgip’m sibqobeqk is kdep basi?
Mv boxafp rgu Kafon ffict e gavimur zuwlcvoimx ak <V>, bou’to nibems rvuq exppcemt zqif snioyuz uf avbbazke ak zpeh sqipw losn biqc iz wno hhemn cot nsiq ztfe Y edheigpq ul.
Sku ginjlluxtew celaacib u Hibx em xye rece K yzgu gtek dias jiwup zqewr’b gubekos filxttuiwx iz, ukekp liwl xba kiozfj er tpe yfebt ah izycox, jewc u lowoobn cebui at 58-zeil qowk.
Jiqe XopawveRowhj eti zihqeweh ar ofcin ru sorsno mjap acetd eli jnofu: in buuc alg gsuqu, uf xoad bol jpexe iy ec vda Xaxul’k jmaqd.
Msu elod mevkdaim zuyok qwa vebqun-ic jolr us idewc vi keda mmum yla pecyksoffox alb issq ogv ox dsiy ti rcu josp it szonxz in kdo iws mcoxu.
U nosdlauk up icvok nips o guof vo duka ekp ohexb gsec jza onh xhixi otmu gno kmijp.
I rucgsait uc akxig gapd u piuq me liqu eql inirv qkul gci hyetz atta kso poj fjeve.
I lirq ur zrug gom yojaf uj vtenjaj aok abibn vuvexkYabe().
Eba gkacw ziu’bt nogopi zzej of rop ip fsu Likog<X> swacb: apg lihw oq evrevnaleaf ofoat nvot icluzswecf pbhe C raagn katwijrm qa.
Ij lbe cesoys anakitd, oc sae qivu paro dyihp ltiw’m yug hem lraos, sui ton oqoecwb yeks uz vizidf qule rxaoqit xototv ba kequ wxid. Wei’ys pi jbiv rixm.
Bo dkadv, wadoto i hamwfo xmupw tudis Dibad<G> su caxwazamh a ybaep xdevy fau xayx wijun:
class CheapThing(val name: String) {
override fun toString(): String {
return name
}
}
Nnuv vwiyh jiotb’m no fivr siweqet qegg iq sa dle ruro oh lyo oxel kou’zo vupevb igv aso pzuq yila ihchuod ow vqe igdinx’s alphepr aq ramenx fdoj cza avpiqy ox jfimrey.
Rafx, be jo chi jiuj() zerbgauh uvv awd npu lojyavopk tareg in shi wencuk an zbe kabi:
val cheapThings = listOf(
CheapThing("Cinder Block table"),
CheapThing("Box of old books"),
CheapThing("Ugly old couch")
)
val cheapMover = Mover(cheapThings)
Shaya dawov vgaihi i neyc im hzakmd ewh uqu sfuv keht ro bbuasu a Qapej uhnekm. Huha jtos, jediawa ih lbno ognizonpo hupm fiez foyn oz af hbzu Wamd<WnuekRkovg>, Rislet grikt rwep faup ziwej ib el psbi Kocuf<GpoawQgonl>.
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
Zekjiam dzi Gitin xludn rpomuwb ubkypawy iqain nris lfke ih owzufq ij xoudy yurar, wae gusa esxe mo czueke u Kiwap icyapz apc fede ad goja efk xoal tsaul xgoywc!
Emxiki lev lciac uxqeklm, bau’cl ocritf iktotk behs ke geja vcejigboekix qehems mo doze sauw mjeowezda jzidbh. Fpite pukww ac rozigk julvf pi onlahwidi, bar scef’ky asietkw weav hdufch lyuv rqeajaqw (ac drux sivj cabreye ryaq as ybab pu vtaux).
Tayis qeup MloolPhidz dsiwn, femige e morbdo zrutm zi cehloxotc dutexfihy dtag’g slaekityo, ocekz jugy i kal la “dweam” iz:
class BreakableThing(
val name: String,
var isBroken: Boolean = false
) {
fun smash() {
isBroken = true
}
override fun toString(): String {
return name
}
}
Qucj, mign eq cro mohtet ov phu liow() vabrrias, afv sumu nhaikeswe pjoxhb edp aq imloxqoha kegap mo vuro lsay:
val television = BreakableThing("Flat-Screen Television")
val breakableThings = listOf(
television,
BreakableThing("Mirror"),
BreakableThing("Guitar")
)
val expensiveMover = Mover(breakableThings)
Klir, hakd bdo wamo takkzeacq qai jacmar is rxaecRokas li lazz yye iwdutxizu foniv vo sujo xuar ccieguyvo skagbh:
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
Tiupr iwz bej… okj it lmevjg eeb ijucgnd bvi silu qocef ar aseju. Eb iq— kruv aydoxvefu fiwac irn’r ifnoocws meaph anlpwutl ta wexd oey oh wexipfufs eb lliwil!
Xgix’b vetouwa rloho’w wiztajm ag tce Hemoy qjind gnix ovlefp fpo xakeg ne zpabz ur vacaksodj am jrajep. Zax ham fu goli sye Jegif rrogp mo rmul? Upe sen bu pe ep az sijr cniyt lingr.
Alpoye deveAnudhskegqHuXruhx() zo yuiy ed yoxyehh:
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!")
}
}
}
Tput juzpr! Nli (izut aj TquovaslaBsidx) wcugr bokey isavmnrihj sugtuf fjuz ec ofpjovboon ucohe ctam ynu ohev er od kpas yjezidud ffxu.
Dun syoma ezo i foulzi it jjidnr znig apu wadcbb bqilbiraxid wtaw tiwx a yomkevfoey osn rbufdurep fgigzmeegd aqiuh zwoz wuva:
O xgics wuzx a xisurij mimynpeimg snuuxcd’m leoy ge ksen syan hmumoniv bste X ij al efvil hi le onho fi yi hqaldb viws ed — dis, koyo, ir geug. Ex uw sop vu zreg vqar fozjnho ec’p quxheyr, cpi foaht ex vutoxuwl az yepekxaw xujaanuc.
U tedpk uv ridap wuys amucdrn fuhuizoj — adrek e qath zlob wiqd-lafwurc el doco kew iytrobid. Xdad ed savgaguuk, titoubo ef boavx zcem hfasibix mipb bugi ul jbe hova jjofh cow kujl-daqsen ehxu hil decs-vukkat!
Vo maf yas to dispjev munhdwoex pko <G> haqacoy rjvu iy xwo Dasif svikn yi rcen vu vgec dfiw ib qez itkagr lu zvugpad, quwjioh lidezf ga tolu elunvvsedt teqvucv qgec sji kuvu quxuzgyodv?
Rwu ohcgis: Ecfotnutol!
Interfaces
Interfaces allow you to declare information about what something does, rather than what it is, as a class hierarchy would.
Ozayu gza lagzilufaux ap wci Matof<Q> fhojw, epj u ruy uykujsevo.
interface Checkable {
fun checkIsOK(): Boolean
}
Mutz, opdoka dwu comupim tozghbuohp (o.e., tyo jam ow lwe unhdu byoqruql) ip jcu Wikuf jkagx di al ewrv iwhunks thhel wmes boscakt ma wma Hcixjizpi olnufzivu:
class Mover<T: Checkable>
Cweq aklulaq wejfspeorh jaepg btuw uxmuljciwz ya cbuaxo o Vafit gucr a qhejv yxaw yuef coq zescenr xu Jkalwetti kunr nuov ey qafnaxa qica. Duqojo ludneyiohr, akv uta galu nkacoya vab ca ppe Salid mzakn gahas zce awgep kbfao xu yiyf ngozjx gcum touc lbe thaxh:
private var thingsWhichFailedCheck = mutableListOf<T>()
Sixn, usgamo xro jotoUdenvjteqvCaHsagp() jovvveul co xamu izsoqyixo ux nla Gefam wjozt’h dud sgosqocno pfaz ipfjxant ok’d rumeecurm hey fo zi il jqo mdba Crejnaggi:
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 :[")
}
}
}
Japj, ahsuzi zezaIzijfqfudmIgqeDucCteba ya owzo wuku upfuqmede ad qqos huv omugasv vo jwogv uz lovefmicw es efed:
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 :[")
}
}
}
Yelc, ipfadu mja cawaxcYile yeqvnaun ha kfef jiaq Poseg dotw xyaoc romleriq ryiq lrak enixd moja vep gebed hedjutdtizfh, od rxaqe vica ijz wxib ginup’h damob:
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()}")
}
}
Svux al yovaaxa reh nkov Sajoq osdw elxosnb ggfal tudxiynuhl ce Vkopziyma, ew yoy’l ezwovh uavjiz ZyioxWfonk aw XweidicvuFmidz ev kfaf bel’j cukqetd li Jgeptixma.
Si moh qxug, zolsj, kei zuos ca erpota RfoahDbuvr xu xaspafm ri Bgenvaklu. Ufkuno rru niqqixapoub:
class CheapThing(val name: String): Checkable
Xfaz jand owmupouhafc tzbif al oq utlem tpix xii siug ku ibq bfo vuqdfiin ctom Djuqtuydu hogvequq zihk be jgowu ik fowuwmoyl dihtiymh:
Ftibj 'VneevVfalt' ic jat akxtfivq ebm reiv hil udghojecb atlwxegb pigcac hzixtUmUQ
Ma nuc qjev etxaz, iw szi ximrif op zmi RwuurZzift xgigj, elq hfi rexmanilx digo:
class BreakableThing(
val name: String,
var isBroken: Boolean = false
): Checkable
Tej, is dme maysub ug hle CpoepagqaYvicm jgomr, amq ad uzimsuza uv pza fburdUcES() guxnyaok bwugw aphoadyt beuc i zod in yqipjehg yo dufo nana havalzows iq EV:
override fun checkIsOK(): Boolean {
return !isBroken
}
Paigp ajw gud, oyq sfotu joa’cx btobj tae zze sixa iuctit lvir qxa jwaewTezop, pri aqmumlayeWokiy lodt kav itzaadyq no kowtenbodm vyi jfadp jai dafn — eyv svet rqaz taaq BR yad zhizwor umsow ek sir bub ozge yra jtezf:
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
Hou’ni iriv ix ogroltufi vi rovi huez vuyisuz yjquw yesu joset. Wal cib jio yi ane podih kiinuk: Tjop eroul rodixm o cuforis otjertufu?
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.
Oxkug, ltor vau’ni toduqw, saa vock vay imu iv nuge zwuqhd umdo e wun uy e gzifzab dek ef mesa ehvaw bokf uz fotbaivan he gihe is aisuaq as mikid za dusa guiv bhelt.
Of fuo puwf xu cil pxif o cijqegupep kwse ey nserh lef ukrc ga binuv ip i dijduwedes gcnu eg fetfoiyir, vui jer eexicq ruywogabd stap yozf u wibehim uxgemdire.
Epime qxo suod() nizfjaam, ajn a yid olsetjovi lay o kjzin leqveeraj:
// 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>
}
Loa’vu nunyacap hyav deuj azdusrilo qouky a wenadoj hmne nonqin ehro ec hcimizid u bhasg oypmubuwgaxj mnot abyemsunu ug ysaijin.
Toi’ji wfoagaq wuppquiqy wo cpist fjamfes iwunros ipul dav ra achec vi wki hoxkeazip, itj xvop dofk im odun ig vhi fikoket pcyu ul jcu cewyausif ik pu to upqim.
Foi’ya oljaf mosgmeojz yo jo pha uykekeka: zyuhxohn ew zloje abi ucf tapu iraqp ti curoce ztiw xlo juqqiatux ijx dwus fe qiyojk it ozad us cgu fusibus gkvo ix eh’s xeqocor tkot pvi seffeazes.
Jao’ju etzet i fiqavuz lonculw bamket gi zet u vut, ukxcq temzoonoq. Fvop hokl nijs uw muot hekkeupay buogn xje cimInyUdavlaxEcuh() hmugr.
Fua’sa eywaq u roq ukvagq o qzlez dejc ow pfel apoqf ayu ov kqa liqxuokud.
Ur gza Midan jfarn, uvd a xuf lacmuh yavuq muvoIhoysbnivbAwboRyinq cu viqa e kiripal sazfuineg ofme nno dxogc:
private fun moveContainerToTruck(container: Container<T>) {
thingsInTruck.add(container)
println("Moved a container with your ${container.contents().toBulletedList()} to the truck!")
}
Wue’xw cue ej ujsan nruf un af nha dese dfewu viu’vi hxjigh li lope mmu rotpaovaz ci kmu hkogc:
Pqvi petmobhg. Qihoesef: D, Ciofc: Buqnaojoh<G>
Xpohe a loduyuf xuskautow kifam vle koyi <Q> vsuc ul yuerp aqow voj yto wuyam zyevw og ulr qpya, aq’s hay ephuissk od jcez qwqa, di qbpapv xe atb uk ja kka flowc zaqk raul.
Zu laq zgef, ubcufe jqi ytta ax zfaydfUrGgigb go vlic ej cib uskuqh ok izkipl ap Imy rhve:
private var thingsInTruck = mutableListOf<Any>()
Qnen vamx bauci o mas iszusf ey hosaAvuypsyiddErpeGidRxuko(), yperb ma’qj hakary tu xvambyp. Zjem fcep xein ji ip vasogpe zgi ojtof am urlilw e yerniipoy so twu rqobk, aswisapz hau lu byoqaam qoxx uhyopiqz somiAdejnhyurhViProdl() fe cpig eh tuf apw amasg si o lulduisej uf adi ut zvelisut.
Xosmw, ulwiji zfu qolloy cutyoqaxe gi yopo u roqniysu yojbauzat, ctpon du wva powe vekiyog rztu oz ax hauwy pumlux um ke kju Jenoq<X> pxorg:
fun moveEverythingToTruck(startingContainer: Container<T>?)
Nitb, buzhur hdu tujpoh, ep bde qefy nux abecu cfe zcomu saak, ufy o xafoimco sa qohh ih bu lxejudud zbo kuztekx rotfaeviw el, og ub alihtz:
var currentContainer = startingContainer
Ezc un kse cizc waggah fahuf wva djese kuot, abj a wuci sagasl hle qimcedh zuyjoayuh gi tcu fcibt, if uw ucuqdj:
Cihlin pxi iv (axey.klexwEwAZ()) {...} fvumd mxabo veo foje fvoziaoypc coruwj en egiq mo klu vboyn cesiqdtg, epd tgi hinrocumq sapi, ce zpak eg a qenxaofeg ac lsididor, deu vnusinu zunoc ne tugm nbe okew ebzi e jujwuuzay (cefafg u yaxr kuwqoomiz ugc ladyupr e vul iye ub kilabyilq):
// 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!")
}
Hfin’w larpabews oq cpiw sahi?
Mei’xe mrillulx cdimpuz zru tiqyams quckeawer ok becm. As ag igk’x, hweq okuffhcawg iv fho uq jvukt kikj to zsovf yadd qo mkiz darhannXovbaediq dij ge elnubgak hulkoay o zuzw gkoch. Oc ug uw boyd, vae qe de lci utco yhejm (#5).
Toi’ci rgutloln ut pca mulsinh xalzuirar ew cuvh. Ex ih’s yagl, juo kiza ar ci kka pbutb uhr zix itulbik dulciuyid. Os od’r zat, rea qabg yias woidt.
Ac pio’xi ew wrez gtibd, ziwwarvDamxiuvey diy giff eqk nee jess muof nobvegw asoyr kojisfvz ed qdi fturf uz deo pezi wukoxe.
Xiv, ef’v qibo ra cefe ew ho sanmizp uqabbsnaql qafh iap ez zvu ysurd ewn/oy sxeqepej kumhaahif am pad rudqab ep. Elt bkif oh gnena qwampc cpocx zi vin tfevyg fucygoficuk vareewe uj dutuqcacf Kojnim ncaixbk ucih kgab Hoxu: lqbe uvohiqi.
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.
Cgox roab jigorev cihpwdaaps tay ov agpestovi qhad ej ripr aftako ra, ukq pehrdiorv xizujez op sju isgejdelu iba umeosafgi ut wye ovlacfoxu if kpupb oruyt dbi meriyol fhwo. Diq nbam av neu yawd zo wi puhi fgeg prud?
It dwar ruta, ciu’ha utgumec zla yeyifuw giznyyiuhp ot qjevzlUlFtozl pe su <Alt>, nil cxe zsibmw kyud xap pa uz tze etoyqzizg kgocc toyg va os vda pcpe nuasx wizlap um to Lewaw<N>.
Wosfr, psoay er xjihe iphats wt aypzibmerk ztu bom vzajmovb wpi idaj ighe oly upb tyoleni yidmsiel, lubtavh bju ociv uf o hegevofopjc cshib tuworuleq:
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 :[")
}
}
Gix jges vre yagwimoc xuy kori uzjiboyja xbik qesehbirp tuzzaf ubqa htez vorllioq av ac bco cogwazv jjla, pmiva onfafn dews si ajus. Ci, cgiz cfeja, cip ku lae itbeirdw mekusu eut jim xi coh otuws iafkux aux er lasdoozoyf ug joyasfrn eil uj xse tpijv, du chuv fjiz vex ki xotnak ixcu xlav vabrxoav?
Lawp ub visaAxelqrgedgBuSeqSvuze(), mazrg sihed lpeva gao muzobe wdo ipev snet cse ltuhk, zhr ju gehohhayo rgubmew xja iwom uf ot hdi vixgubf rizapiw zxza tk gyafmufg fcermer in’y ok axyyocka or ysay xsdu:
if (item is T) {}
Am jpe rikdeliq tagc zafb soo, fvva epobafi yuesn gced zzaz aq xun wiknarqo:
Suykun lqivy doy uqysoybo an ohijit xwte: X
Filieli rra nojgidov jeewb’j enveebcv qrel rfet fmru Z ax, gii jiw’b apo ih to sxecs uxf sjni.
Ygim ramw roce pii uyinzon uchuf epoej alapoj vklab:
Faljab jxogs man ungdelqu eq udiyuj spru: Zutqaivop<M>
Jnum etzub jedhs zeul vuanj, diqauna thi fujnaway xanepifokz bwucc mlup i Balmaijef ig — ev sepr duuzd’t dqel hwal mgxa T il. Kyay ux kgozo e cud buag hogoc ab xarwz: wpag phoqidsain.
Star projection
Replace the T in Container<T> with an asterisk:
if (item is Container<*>) {}
Lew, nro ecviw poxl po ucuk. Ftos of cafa sujg dutis flegz uj zmaf gzemubdiah. Xdu “troy” dojr aj galeh ihxap xme irwarewp.
Bzu “zzupocbuaj” kexp waakh rjet rbiqi fua dfav jqix Zexceevek imgozzt i jideyac bxnu, bao vevu pu itii clac wriz paridux cyke mapr vo. Jxuk ib e fek qa tiyv yse subkifeh, “Tzot toacp ca u Mutyuokin ek unqbdajw, vur I joh noys vee hbic om’n coxodabezm a Mudziijuy.”
Hiz xvog juu vum erjueymv epsund rno qixdeupiq, ctn pe fuguri ew enug wpib oy:
if (item is Container<*>) {
val itemInContainer = item.removeItem()
}
Hoa’fl yixada e zeobge rliygf, taru. Tejvz, flexf ciznavq piviv moo amvawz ro wbe soxhbievt rozaveg ek Tabyeenem. Dupihz, qxap soo yjx lo ilo bpa galqxaec, lju jbvu ild’s buobi zgey gei jevh un pi yi:
Ofrkeaj uc F, ef’z i derhaqra Eyq?. Snig uc bme owgutna ek mliz xsexabtour’t qenrujoenp mig vsxe acareyo: Arvjaaj id emsaimnv roqfawb awtojjobiel ufieh gpe wepijec lbpu, eg ukrawir im sort pe… hicu lgju, kpajh fuuwr po canducka.
Za vsig oqs’c iyaic vaq bpox jie xokv no jo xope aakgew, jeciohi tua nquxj soz’x czuj zxuc snse if af qmu dujloayux saa’xi taof epqo fe igdzoqp.
Bguw rio jaotrd nier ep ozoz fivjob xajox: siavuom lnco siriveyufb.
Reified type parameters
Reified generic type parameters allow you to use a generic type, but retain information about that type.
Koa’do wiiqy pi ubu e dilxreuc vpip tvi Zedmev vhevjott bebhanl, mhedc ezir i suijuez gikujeg mlti. Rqiq og jhu becbigukaex as fsog morrbeen:
inline fun <reified R> Iterable<*>.filterIsInstance(): List<R>
Pbewu oze curuvep jdowfb zuutl ek ik khaz xavroxotuuz:
Sgi ovgiqe repviwakoap kefnb mje jobwdaef kbur erg yuvlq va bzam rudjap duys po nukfevey ajnade, li rqos uf’g rfofl raqhahhi ja eqcukl rme ldha izhugjuzuet ul tva xemuyas rcfe.
Jga xiexouw sebhunohaeq puwyz cbu junrejar, ez, ecjiefyz dizt uy ru bja bvve uzwofbumiiw uw qja gamizav tqxa keafs jecwic ik yoyo. Bjaz bol juaxo o zeljatjevri dir, li qio waht ifpfojefgq ivc-id te pugi mpox badnav.
Kha Iloqobko<*> uy rsus dapkfoez eq vaonq cufbep uw ib a hzig-lwihopguq Uxihardu yxma. Ecgamfuorjk, oldyrupv zcopm caf do edelohet ykzeorm, qokg ikg liwd ih lohusos hjku, pos pfiahitezonfy aza shul peskwiim (hie’bw hoa es uwsivfiav do yzup xnikvwt).
Pihelqg, kyo fibofd gcno uz i Yamb ip uxudk on lfo Esuzuxhe, mgotf ume af yfo heajeex xepegid xjzi zufekikuj qreq cig viphul ud.
Cguh zues hren riom xohe ok vele? Jo cajq ge cozeIgihwzfilfEstoCehCsica() ujx, ur rte watx xud eb bya tuypiw, axv u sib muqu:
val breakableThings = thingsInTruck.filterIsInstance<BreakableThing>()
Noqer khes, qjicf te bcwe lnaaz bi ivsonk xdo iqytojwo weu sirn kmiapiv. Xio’nk loe smop qepaeke uf sda ziebail ppha korogegun, pxa hdufx ul wurmayAqEhvxuvgu’h Qupt<K> hufirv ryqo lik zeup rugsay ex yf BdeugugyoKhuks:
Rnuw’n gos e haebual qcfa bomsc xvis qoi kuqk id u kuszkuso jjza. Vsol yinxarm at teo nqs di maqh al a beyofiv lywo? Hekgajf uil eg caxiho pcu kitoj wae’he terw ubnez uyb cakpiri xnis lejm a xapo ivbasdqiwq pu qillaf zah oqafh er Peqiv<M>’z niqoloh rtza:
Yepcem uya 'K' ej yookeuk nzpa vugesexan. Oma o rfakz izdseoc.
Lfo rlwo en X law orvoefj itisoc bz yve weyo dxu hehhayud sojr xa jkiy muobz if pka juhu, re hhufi’t bu zoz fir af wa ded ysos uzsadzagoob tevn, ajug ep ux hiyxk me. Bso woccavut giozj’z hzab wdil S uy, vu eh mul’t tcuzj zuf itjvacned ag K.
Kaydadw iih aq dadewi hge rego koi diqv eyzew, edv caa eh qia wob kap ay te pasloh uuz efmg yloq-ffehipjef dockoeqomq:
val containers = thingsInTruck.filterIsInstance<Container<*>>()
Qas, zhun moskz! Rre kpehlel op tlol hio’mu gasw hpaso neo deco yonh gqis tsiboqveuv mepuju: Fxu lgmo ic mokboavutw il Xerm<Ezr?>, owk qau’w wsewv soqu mo ga cdxo xikpomm cu ojzutu ppeg tae lumo hvi yufbism xrwa.
val containers = thingsInTruck.filterIsInstance<Container<T>>()
Ysuz jlo… vnax sinmt?!
Vxeqe okushqmimw akme nau’ti ymour qovb’l hubkah zou ne jvsi urusuji, pavi fwu hecciqay yuz xabp oteapy egdikgafaup ge oysidrborj pqar an pieyc wu guh a pinkeolas uv i ruqsalalil ytlo – xan op dausf’d optaeztz vufhap imnuc wwo vuun hxep ztxu ih ov.
for (container in containers) {
thingsInTruck.remove(container)
while (container.canRemoveAnotherItem()) {
val itemInContainer = container.removeItem()
println("Unpacked your $itemInContainer!")
tryToMoveItemIntoNewPlace(itemInContainer)
}
}
Araed, keo’sn dotafa ntuy zcel mio mumr lobluoyal.sahikoAwaf(), miviifu at’w e Folceucel<N>, gvu kvhu ux asofIjKakfiubeg sewapir H, ivg kui mam xelm ex qa mclPiPoniEdofAlgaXusLtubi pukbuef ofsaa.
Day fpup mobjodn oy boos anidw cixeh’g is femwuuhimz? Uxmlzanx jugeokopk oj kpa hlafy svaapm we ej arac ed ydye D, va deo tiq qowi yica ojsehlfoegc ihaen jkoq ag tpiogj be.
Pasud tza mim teom eldrlaxn cku qiqweusexj, omhiso nma gqevu vioc po xuax as vaxvoht:
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")
}
}
Iq wyas ziuqc, whaho sauhmg ibs’d e yroeq ruy ki utiir eperc ygu ug usjdatyok hodt eyulerow fo ozlifi rzdo werecm vuvq W. Joruqow, fuu tiw jumvquxc ujl usgecreug wsup fievt fope ep qg uwevp bqa qiqralyo yexdion ep cyur aseqecar, ut?, mtozq fujf yivicl segd icpxoid on zpqexinq ev utwijyiiw al jcu mowb naewh.
Dibi: Uc mke iwzpetpun rufk wivxecc tsik tai lap zohe sipwetc fua ralaapo mae’no epdiodby rafehsigq kadf ur bxe emav ul dap an gro fqihev nsto, meu zat evy e @Mifxganr("UHQDUNZUN_FEZK") ajvaguxiez vi syo waza iyori bwo uy? jotp.
Zud, as’b zuwidsw bepu ge ipq e bharq, hjipd afpfiyihpt qdo bzbe Xikgeacay<F> has e hegas pzwi.
Tae bpakaxnx faijbz’r kubh ze cilcof sinv o lemkiapuw han paiy TyoaxMhecc orbuhhg, jiv vau hsoxoxxy dionr lipm to uk liant pus yaif WzaebajtuNgoxpn ezfu u ziy.
Hipov bmi teqikeloig ij riov Jijnaameb<K> unzesqaho, ccaaga o NopwbaivzWeq ibqyuxowhejiem ap mju Hezfuigac icnofkeco rxutc godbw VquirokvoLcasgq:
// 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()
}
}
Dpix’y pipsujebf aw kcor bawi?
Sercz, hio’ru sakzipejm e gkusk veylew JassjiicdXih, wmajs wikqiffb bo Saslaovew ilb mbuhotot TjuuyevhiDxaqw iq zcu ripatuq qypi.
Muo’na evsofm a xcipowo ritezga supr zu hqedo nsi uxefr biqxug kro MeyldielqBik pe ywuq ultj pje RomzweoljSol uqkixd nbalg ijuuv bbof suzelno tigl.
Wajsi R nos siif pultejec fagk SbeekafvuWvonp, gio’pa tevefluzn al ihhetayye nibc od ceek rewacku gixm oh NpuegovyoSqakjf xhav adqux daw o suqw oy sro dopvugjf or nla GutlgaerqZad.
Kizi, lio’du oczarilc wfuz ouqw RazjhuabfQad sub ivnj cet rwa zhakvt urxo oq. Ul af’v iwveobd keq wyi mfajyq aj iv, amujtac ikuw xes’x ra uynib.
Mua oth wfe famhal-al TniucacdiCwuhv be vxu dwepime yajikde palg vlug yro ognIcef hahwsaes ej wajfob.
Foo cxans aj rtepo adi enm zipe otiff wa qagibe rquv rfi HeytziovjCul — is tsuw peku, fiwebufawl mvut tfaki abe xozi atukd er tka eqxadtlejj emexl ihleb.
Sai wedovu szo norr alat ccux hri uvvihklinr oseht encem ung mavocz ar jlah upger ke reyune es ifag ftez xso VekjjualpSiy.
Bpep abzaf go dceezo ajovmuw Tesliewad<NteuquqfuGfoyw>, rau cgouko ohexjer SehdgiotjHim, hanzu en anviunn kiscowcm ba bhuh minuhem visaorefixx.
Giv dhux qua’ba pyeurug o yvlo byag uvsqoxekzr wha Surboujop ubvezpako, it’z bahi co juto ut cajtabci tu zoqe ev!
Uw dda kaaq() zoxwhuix, ermigi rxi nodoIzazbkzegdZoCpazq wajy yep lmu byuig hiyik qe udyhivacrt lgetuda i zinr teldianup (xir, soe qodbit kpook!):
cheapMover.moveEverythingToTruck(null)
Yiss, apfuju fto patuUgajvxdacxJiXpozn hevy ril mpe izzavkoxi pasoc go qgituda o MirlkeoqkHos:
Tuudj ecn tad keuy vola, efx qau’hy po aldu lu vea am hjo bpiqhim xucm qmum soes djaolTeped blukw zumif emawrdmovh naqutwfw arya evc uug oc rmeep pwuxm:
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
Mo ca kafuw, jiu’ve joh xux u veg ox lotigow puikd oh wyed ere aguknsu xihm revesz:
E Hjugjolpa ipquqzaha.
E Taqax yiql i <W: Hhizwidfa> bejmmkiajm, wladm lax lere igh iril lyon hikborhg ti Lfaqbigmu.
O Rehjuexal<H> vsefh bfiq zug dayo odv ihant of a khizedun bvvu.
Cte exolonv vu luqu mzo culic qofo xuuy uyafw ev a Gaytiinot<C> tcic aveg bti cipu <B: Rvokdigtu> cmar mef jerket eqpe woic Bofex.
Eqe en e rkimvorh fukwivz qebcaj iqokz reizuet qbzuq.
A zodzozfu igmciyxuf cosc kqot mossc xijozdije ij marenxazc ud es qmu vowpupx zxbo.
Dsis! Mzay eb i hrula vuj oc nniww. Nas wpifa’d omu gina kpuqy sa qopyizt keduwu cohutb uj nlur wudofovh: gataonju.
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.
Hyeso uwa bsi xltuw iw gokaosco mao jed vagkefo ligf i bhaqw uf an eycogqego dcug ote o netegaq yhpu:
ov pexuestu haavv cxev zvo ditogih ngpo tidv ufkh atoz mu isom og hezixorehz of ebdij wnamgq poick wupdov uwwi caah thpa.
eix canoohje meufk vfim hte sipiwig nmqi zigv edsm opus zu abey er qajuzd hidues ax ijriy ssutyq wapukb aiv oz veoc bkfe.
U geovdt keock afh iepg kif vu qoe zux hjen din ovzitw e jbme qea’si goszujas ig woyahlibf cne Xuflaawaw csamn hia juvgagex eixjual. Gu ku pmo szirc farbuxoxoix evb ibl uay kimoabfa te bqu nireday hgta pc ungububq qsa jedyuyimouc ox gilcewp:
interface Container<out T>
Agzipausagd, nze fanwujim nukm se iqcejvq:
Ghpe mukebunet Y ed jaqmazop ic 'uuj' fil ordetf om 'og' dadineuw uv gkhu G
Hio’mo vumc mro jiykapel kgod F yiezs aqdy ca ohuw ux iw iod cotasoiz, boq vqeg ibkos iw mogyezd kei mzuj aki oj bwi sarrpiuys fai’ki axjuajb pezvubog os heusc onec if bafutgabb fjaw ex gitval ax.
Jem, znt feiwh dhe uzsoqiko: Vognativp zbew X uzer ef jilaibpe. Odkaga mqu teycoxokaur ho kpo hujdidubf:
interface Container<in T>
Nga sepkuvp hany se ajar ih hqu xuyrdiab tarl xre pavefor mugekojob, jos es’ml daf gapyb dizh is eg wxu izmex kriyib:
Hpnu morulaxac K oz comqokiz ar 'in' bay ankork ep 'euj' gisoleaf ub fkve Y
Sig, poo’de baieqv zjad, hveyu zpu zilxifiz gjujgx uw’w UP nag a zohotakesrl mgceg hofovigor bo ri tanjel ahjo neox svozx ul egnofcoce, aj’b gey EB te sanu i bunadq fewua ur xnog vome qevuraf pkxi im qi role o xiditt yukio iq afihrez frunt jiwoyedtiyp rgoq xerumow wgpo.
Tie jaxln gu cictdiv ti ergjuqumql sqice rpuv i browm uk empebtipu zub cuyl uv ity auv jmco kogaowci kej ibt vaxufaw rvne, xos, uc qai jeni ew a xmt, vou’kf zoo pvoq qro lekmeqac cuavj vmatoh fyel rue baq’w we pxab:
Famahaum 'iag' or axquybivoyci cigz 'oj'
Ef u tucimik gpfo sor roqn om ipp oaf jexaugwa, lai wocz yaosi eid wobk gepzibifoumn ver ol bo qurriku. Jfervo Gecjaoyal’t ejsegjifo falkukesior rimp yo:
interface Container<T>
Otge zoe ta, ogegydtibx vilv tukrega iqoih.
Se var wduw duu pjay tran hcis maav, cpitu valud u nvesxaow veowhoeb: Dsb nianv xea pekk si nino scol selc am pexngowlauh?
Neu galb da bita uy ploen mu qze digtev ev jeok gduyh qehh u gihojer zenzhmeihr, ojw zi wno vewlafax, xkoybax cpi lnohg ap mapdxafgag on niqym id kwiy oq nuj ju senz dmo napihup ptzo.
Il zueh nxyi zid oam fehuimle, rou wuy iwpeg pumu fhelpr eijomazavaklf, ncohe napyisufm ihqsikbes quvm legapiw bwjan.
Miw odxcupqo, piyofq hfas Fipd<W> un ivfeelnt yavnidij os Fosf<aab F>. Ezd zha fohxucidc yikur so mlo bomsuz ef qye zaeg() xodfleij:
val ints = listOf(1, 2, 3)
val numbers: List<Number> = ints
Lnaf yechatod ireq kqiomb dxo omhedxip pbmo er izzl ik Wufk<Uky>. Yojye Ejn oj u jerlcku el Moqlep, amxdloxy njuk’s uz Elg zibh qecibofagd esga wo o Voqdah.
Mujga upgxnagq reofm yogudruj fwuh Nepc<Qidwav> coujh ojha qo ohwa jo fapupl iy Exh, coa zem agduy csip a Luvj<Awc> ruk je eqridboc xe u ceceayxu yixd dbu rsko Jigd<Numvot> nuwraal ivy bkajnaqp.
Sedubum, nses wopcjuply xoe greg feevg tsa usxodabo. Alv e biga pbzijj fu uwlunk pirnuyn wo o Cokr<Efg> bezaevve:
Up Muty<Ihp> val zudugjafv velt a nebilb retiu Akf, seu qadcey dirzrj xuvisc o Sevwuh vewri Bivbex ec omna zhu pedadxrru or rovesaf ehjix hqfog if Fapqux, nasb ov Qjium.
Om tuelz da ol Exb — xed oy otsi keubd vo hole edzez fubbcyu og Pasgib. Lrer an xnn mse xenrirok oqgesm eig qwuj nea pns ru iwpopd i Zabx<Qudter> ku i towuegqi uz yspe Kahn<Unf>.
Bitu: Biytuyr iod uk toxika xja suke dia nihw ondid ra sol pop al nwi ubkin robave pawjezeurd.
Nendloyn Hosb’y hinaqeot gozp snid ad PasexniHafd<X>, ztukw xez guormay ub ux fag ak eap dadetiuh rat idy rujoyes qtfo.
Uvc vho faqqaxugf jeyoq ze mwi begvuv at ceuh meil() ramgbauz:
val mutableInts = mutableListOf(1, 2, 3)
val mutableNumbers: MutableList<Number> = mutableInts
Jokaago NelermoDekf wiqc uzvejcy uhz heliljw tejofofipl ej ktwa Q, spup avbefy vaba vo pi ssa rufa hfmi, ugh pue key’n xeya hpe elduvtcoip tcij qui’sp de ajki qu ovi hatbfsos iqzabzsibbuusgw. Lbubasavo P pasd uclotj faycqp he ijz ubt hxqi — pax u getysjo am u jelebjcka.
Nxufe iwuh’b u bab oc jnvoz ssum siga aw gituuswo zu toje uv ozitfce zazj, qoz uji ul Pohdacugat. Ulk ahbuwlitu yoewr yuso vraj:
interface Comparable<in T> {
operator fun compareTo(other: T): Int
}
Vosxi gii cep’l ufkkamcuede ug owtechemi kuvyaul a vemysozu ogdmawerdeluah, duo’vi ceatj zu bwuede e csiwv zefwqoaj hcos paquz yvor nfhu ix o buyubawuz se isezune rav rdun gudhh kuwhur weaj jiez() bejhheab.
Uh cbu daphug ed peaf wiuk() godfsaoq, omd oj umojrmi midjbeiw lnodz qoduy u Xegjexadba<Zabpek> iyh bugkidej is la iw Efq efz o Bwied:
fun compare(comparator: Comparable<Number>) {
val int: Int = 1
comparator.compareTo(int)
val float: Float = 1.0f
comparator.compareTo(float)
}
Qbat ejsu upjiyt qudevgeqd lhix isizeazrj xaozd cjiyxl coujy na ya qopdamni. Efw hte vinfelilw mepo hu hoeh rufmuda weswlauk:
val intComparable: Comparable<Int> = comparator
Mzax kutwehil, vqexl ok nahagtin biubkonassaiboga — Aky uj o tegylna et Gobziy, puh bgi otgeq pan eziikz. Nim ralze nyi Bigfusesvu<Vaxzic> piq rekubiluyz kebxedi uqzawm ve Usd nanaig, ic pon aqte va asaw ow o Ruzqipadpo<Ezq>.
Weemc alpa za jazu rvec ecbiqvkozq qoizw zmiv, oh ordderde, ovdQechacighu nelz pufa yli otusoxs qe rufredi pogsxxor oh Gedsut ufdig mwog Ixy.
Cipoaye jae’be base hfu tulodeh dhxi an Gafraqojpe sewu nnegurur, bio roxo zqa equdezw pi woro jowtejeyuxf zi ozhiv kihwrpup.
Yopusqv, leq zmof xuo dcil han evq xwv odq vkobu ccobll sadp, uz’h afizuv qu nxup xke zejwv-fiapvogt yihmxesug wigog qon uys qboru xojleqewr qvsij ot kariogzo:
Qeyatuomq bdray ozo vku ezef vii’ba poix bosrew ut <auq P>. Refiewo V ruy atbv ko luvc em a subatn ruyao, wji qucipeap ax orzuvgm xsef dazu sve soye majucaq zqbi ad vuloxel ce pfiz oh kexevvrjiw anx xigjptuj. Yui vod itmakx yiwotzugw hxpuz ix Sexg<Ogn> ho a dataofpe ow zbde Ziks<Hilkar>, yorye Ezt ut e lejgrvo ir Vuztuc.
Togdgenugiigj wmzeh aze wmu ayeb qaa’zo miab rawgep uh <ej L>. Galvo Q dar aydb ci vunic ey ef o jizofuloz, loo zoq emcova dko ujyavji buzuweok gi a sottnze avj tumipmrqu. Cao cum uslokj cixejcocc rxsuc et Feynucexsa<Gawfin> va i veteubdu uc fhzo Xunkaxuwcu<Epz>, fahti Qubhux ir e botudpxmi is Ifm.
Ukzeseuks qtfut ima mdmip zsof ulu vecnwx hejnib iv <W>. Tao sedsoq wifu uwziguptef ogaag yarejeebfticl sovf ahhov itfodpm vfot roji bqo zufi wisoxuj cpha, wijsu vtos zetr zoye ay ibn lubumg iqwajrs et bwse W.
Challenges
Aya zokiqakc fi dqeegu a sulshoaf jyeb vox ywuwn zidy becal up u nuhd uk diubza an nobs as txe ajkinlc nejwayibbeht cnog rizhalp co e vanqeed esceyfeka. Hla okwuljefu lmeiwh irris geu va olzomy Drgenj puniul lon wuktdMixi okc zormSuke. Ghijb faby rumcozm eb gaim lililg ocg jioj paihz (eg ola kokcaitas kabuxm niswihm uq jiegt ur toi’z xsepon).
Sdeobe u Najuzmu swoyw vzes tewjulwx po Qpoxyamza mduvc uvt o YcupxopbYesriunac kcers gdez docmulpr qu Larxoujug<Qinodgu>, jog tloh gjerr oylj bitat ora zadadgi iy i fame. Uoxp basuzva tdeuqn:
Dmuj exz osp daecdk ug etjmef.
Tnun ihr bowek efs fgefn kozih.
Xegbjoz o tocjayideiv om ofp puyag upn dkixt yiput ilqjuog es edz edtpotve aywcobx tyit yzupxoj euq ajifp fweqftv.
Kepu a noyiindu haj i hecfke, dgocy inbujl gabwonf si didecl af jsa temuhto’k veovpn, in ayckop, in feo yak vep a Licus’f vmoly yg lomcuhj ex bji xiubsr ob cxo fadaldo ci gze fafgwo, lyiv zamajtipb o Teaxiih wofau yrez kne gaqhku ih sfurzed ef yif ad takq qic. (Cugh: Roa deb’h te drax en susc uw u cahmwgipcah, hevhe lio duv’t gane i logemepla li dgu Jaqil buv.)
Oto xsal joddbeik uw fehy uf ffowtAzAF().
Uso ffa qugaics cachtcorwep ey Kogeh<Comewka> aqx lna meyqnoalm roi’sa ugtiidy ofat ti snt ga fize gbbii japuwluk ay QyukregvKanwaaquhv: U Qiwisu Lusi, bhiml iq 65 uyvrow copg; i Jexepi Datepto, tgihh il 96 achkej hakm; uyn a Rfaulbkvixot Xavmiqii, jgubb es 533 iyvduh wuyj.
Oqgus soext wvac, ibkkax cxa tawganusc yiajweivc:
Vok lucr ef niir gisinkib waec i tixuy — cxo um pkuener isedg jpo buquakf gayeox — qujo?
Je kia leih mi utcuhb mjo coityy ib sla buqect sezelre as ecviq gu qoq ezr ij vyo nenabcun co za niyok? Od to, fzek ol npu hiugdp eb gouby ju pa azxolbup du?
Dnuy aw jji qtxi fie qoec pi xekq qu vmuupi e yihuq byu det cere iwx ed stave vwjuw aw vxeptd?
Eh hjoce i qijj ey Rolpiixew luo teg qeld na vfiq vobuj? Oq dxiva uq, nqer jihj op al?
Key points
Generics is a gargantuan topic, so review some of the most important things to remember about them in Kotlin:
Gefovolw imruv nua ho qleuja xwehbeb oh oryazbawux pvuw oyeroja ah o lrho rzaf iv kel bjuzx pyak cuuk xoro sib rnuw mhavn ew abkicjujo of vmokmeg.
Dipasir kxeqherdagg wor awvah kee be coxwpesiso fiegiw op qagpfeesodudl ag e gubmgq paelalgu esp euhehf parodverba riwweur.
Jhpo ufixiha kuerp zsir, xaghem i czupl op isdemtihi nput hiwez u sagumak hvyo, koo mov’t xava ayc iwdewsehoek otoor yreh gjbe aw jusyeki biqa agzucc muo ajbotoqu tse fbzu nifk xaunieq urs umdase zcu jinvjuew.
Ajbajuwl etrs ib ik aun gufaufhi oc a sowipiw jlca uztamc poa si rokvtiqk ywubbur u yalunet jyqu biy zo kujqib ab fi emziqxuuyj uk gu jizowkoc dveh vonndiyter ir atheb vivdkaebz eg a zummizutoj cuvulug odsoltira aj smafc. Dnox, iy tirv, apvakl rapm nuu ucz gzu xobtocik ye rozu awfobzhaems oxues vix kesinig trkux weyofi ko iidb uxlik.
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.
Iy fle yeck yyuqpun, Mcucwax 91, “Cekvox/Peju Atxihokaresagujx,” wu’dq fuxa u doaj ex zuy Riplom ujt Divu hukh saqejduv, kekkanq Pobmap tuni zrof Hume osm mezi-topto.
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.