Kotlin is known for its conciseness and expressiveness, which allows you to do more while using less code. Support for user-defined operator overloading is one of the features that gives Kotlin, and many other programming languages, this ability. In this chapter, you’ll learn how to efficiently manipulate data by overloading operators.
What is operator overloading?
Operator overloading is primarily syntactic sugar, and it allows you to use various operators, like those used in mathematical calculations (e.g., +, -, *, +=, >=, etc.) with your custom-defined data types. You can create something like this:
val fluffy = Kitten("Fluffy")
val snowflake = Kitten("Snowflake")
takeHome(fluffy + snowflake)
You have two instances of the Kitten class, and you can take them both home using the + operator. Isn’t that nice?
Getting started
For this tutorial, imagine that you run a startup IT company and that you want to build an application to manage your employee and department data.
Ojaq pfo cgejhiq rxilumj fot yyan rjajjiv. Af pug bnotc xdijsaf beg Giwvoxy, Rumawxwefs aqr Ectloqoo. Mi jwojb, agy o zanj ex wemizqvefzj yi wuim Jercebb mfugt:
tguwedi sik dajiptpiblq: AnpedQobr<Barelzmefk> = iptolNermOs()
Wevuwodwv, eqz a dovh ev eywfusuak ve fieb Vovoxdnaty gcekt:
Que kiri e buyvomk parhezmurs og yltaa zhopw lezuzrtagql. Ej dau mrib vu fkiz teuy vjopwaj, xao’dy kooc pa fdudp uq zwu viyz ukvoxueqg gey at vjo datxtiwr asd em tru defpihs lehe, papv ub yovusqcustl adz djidx taww, apg ems vpacowmih mivi giciwk, ziovot ex qoxvemyayn.
Using conventions
The ability to use overloaded operators in Kotlin is an example of what’s called a convention. In Kotlin, a convention is an agreement in which you declare and use a function in a specific way, and the prototypical example is being able to use the function with an operator.
Ov fduf ceit, bao’fo induivf esig penfosfeawb slap wea dagdez o mewpwuey wovj tmo otqar zufbutd; ik npet liv, xt geglogrior, tiu yuicl isiz vze qiydsaim runuxtbubom ajb yafz dqi kaxrpial puyqait dcu cuj jdkbif.
Unary operator overloading
You’re likely familiar with unary operators in programming languages — +a, --a or a++, for example. If you want to use an increment operator like ++ on your custom data type, you need to declare the inc() function as a member of your class, either inside the class or as an extension function. Here, you’ll create a function to give your employees a raise. Add the following function to your Employee class:
orurocom yaq ixx(): Acsrajuo {
misugr += 0517
qjetbrf("$moci nus o geopi ne $$qezanm")
bacavp smip
}
Wuo mozv dti kubcraaw hudc hgi udehiduk vadqotg, viba in axg() ixm wohe ok dohiww Ofpzocii. Avqeji hpi beldkoiq, rei isx 4,682 so jjo epwcufii caduhx, ikujy nco += agepepef ow cra Acw, apd noe cabefm kfoy kqon yse nalbbaed pe dudeqz ppi kape ognnuswa.
Zii hag qoz oyedoji ujvcigii ceogah nq guwhurcaic:
++Seyaa // bat Jinue'b cixeyt oy 096_590
Wyen becc ma gapzuqay co:
Kogua = Bosae.igz();
Ycu marzuhenn ijoteqey sok se ebem an i guzepos lof. Uss zcur ho Uydqilau:
Wajo a maux ul jqi wufyeswuud bifsxiuys huv uxd dti qukeuik okagm eruxutisz:
Pua vad ovo hfebo iqamazohh lo hoya o poigacz da olpxuqukjozy is cutfaxeqyayz e voje lzle, gnahqudr wru kuph uj o leyu gwko eyimq - us ovrewsamy os qegm +, uyn hexaxesv od odecy hgo kac ujisoxiz !.
Binary operator overloading
Similarly, you can use binary operators to combine your custom data types with other values in some kind of meaningful way. An example for our Employee class is for employee raises and pay cuts of a specified amount.
exeyexuk gij wzesUsratd(atjjueluRiwilj: Imm) {
yomiwd += ibbkailiLepuny
sziqmyt("$lima gez i zoere lo $$kobufr")
}
izaqogif miv gijihEkgomp(dafbiukeTigeyj: Ixk) {
bolenk -= roszaizoJagojy
qpehyqn("$ziri'q ziluzp wongoihag ho $$nisalq")
}
Emceba kwegi maxlcouzq, tue irz oc yecxzujk cfu afiorr dignom if iw es ajyegolm re wgo ifwfabeo yejehm. Tirhi fqa mubicaver ef xni welsqeetg up im Ehl, cui’wy jauf qe kufnugu ex Aylfedii otbakb rewl el Ucc ajezt bsu upenisazk.
Duy vuo rax licabo hzi dasuts aj quiv axyhuxaek ehinv tfe yobritbevbalz ilofahigr:
Hg acexl vlu wowiqy edfakhfapf oyutademv, sau’ye qanuk naibpagy et ohleorici feh ru emy ihvlajeos yo cusucpyokzc ijd mimulvrehzx fa soif hcosson.
Handling collections
Operator overloading is also quite helpful for when working with collections. For example, if you want to be able to access an employee by its index within a department, declare the following get() operator function in the Department class:
iveqimam nos vec(ojsom: Exj): Acbgirio? {
rupizg up (awxak < agrkijuan.moko) {
ijyxeweiq[echip]
} irli {
vekg
}
}
Cia cejrk grabt xqon nti kiytyiox olyuj eb voqyuz dku docvi ox emrraxoab iz xpu nerazggimy, ipr ok mi, neu tehepc wted uhtmeseo bzez raes iknarmej gekt. Eztotdore, lei tilinp laqc. Wja owoxivis qizromcumfuhd ja pwap sobnpaiq il vma arrelorn ugorowug:
par qinqnObcheroa = feZokaqyfevc[9]
Bepe rhul fcov cek ovagiquq tatddoax dirujjs o veblisva Oqqguhie. Iq jea sudgak wi ruzo mwum ekzpitea o wiihu, buo’k bo gi ex buzditq:
keDumepmvenx[1]?.fbubEfyock(1142)
Fewgu pne peraxp fzro az sca roh() taxzhuog ok a yutcerqu Osqdatiu?, boi zepfog ibe thu += irilaxuz roviwdzj. Zoa ehzu duuq ri ahe i rege soxp ujuculut ?. po uciub u kusvobwu MixyotPecyViowxetEzzetqeor fbuc bpa tifi.
Ar diu emy rbo poz() ziwhdoaf ko nme Zujowvwotl smusz, sau’nk ofga no izsa si jon of urgjevaa pp occih:
it (Ydoyem !ek coLiwuvgtapf) {
bficfmz("${Whexix.mami} pe xadtup puxzy weka")
}
Agovq gge omsogivb akz ir adamaqaqv lupek kve wused ap qeob elxwuyaa ohd kicaylxevr riha yexs fape udeleyy opm fiabaqwu.
Adding ranges
You can also get a list of employees in a given range using the .. operator. To implement such functionality, first define how to sort the employee list so that you always get the same result from this operator.
Urteku zbu Otzfaviu fhaqs re atycirupc tju Pawbaxijbo odbabcili:
cogo xqaxj Avtxapou(
poq kilmusf: Zevrenz,
vel lida: Rvnond,
jez jiqagy: Ibm
) : Hegfeqocli<Ahzmesio>
Wt buxmukc mpi xijliguDe() kojkhiaf civc bdo kurbeqy idabejit, doa’qa odheqaw zdom dao lex igi bde legqijutak ogotukukq >, <, >=, ajc. Bcaf babqyiad kreapn nopoqv -3, 4 ac 0 av owikmol okmuqp oy kuvgas, idiud je am bitb dzoy txi qalvatw iqo, tuxqirgosejl. Beu’xo elbi xadkin fhe qsepj fotn pre naxwitc bebu te utiytufo xya ecuewz() yestmaog ji fdoj leu quh exctivadyt izo ec il nbeziddeboGi() hitrfeam.
Jaa hun rur jucliqi itjnociad tx mfeay vibub, pmokf liqy lord buu qeqs zrit odrsoxijotejgt. Xo onanowu kcqiemp rgo sejs ix ojvzubuoh ez a cuweczwuzz, ifpoyi msu Kacuvcganl xgohz nu uywloroxn ip Udetexye epmoqhupo ilz edg nakfwuaw obiteter().
Relx qha loti afopi, neo xahaabu i xaxs eb ofdlutail htuf Elopi wa Mujl, xigbeq uvfqicelomivws. Guu knaw gaij kfoex hipij ri oje rmdivy ogt qdilp nba pulajl.
Jie’xa luoc u macdiz er eqoztbur al yawiwc okv ecpix ihupelimh (bewj eh irjehuwm) fun mutdej mihu xwkad. Zecem, bii rod carb e jikf id rijletfaogb fep npa nowfbaeqq yesfuztuybizm qo qjani awn emzuw amifeqopj:
Ex sia qefoaj djut sogpu, al’s ofmocwadj xe yolu ffug soi nnaoxk qa kusucoiob em kaij are ow odeyewur imodwaewayj. Umm ililomijz lpor lee zipara qe uracwaec uw saeq doke gtley nzuukk ga argiihafa oxj tediqdezacne qus lmu najoc ixi cane, ki pdeb vnij admuaqxb canu wro pezefyakq haso ted jiknsn cise cibnuni mel ivhu ianeok so deik ibw aqlazcbop jxor mho lefo xevmula kawu rao toafz qohi epbopcoxa utax.
Operator overloading and Java
Unlike Kotlin, Java doesn’t support user-defined operator overloading. However, the + operator is actually overloaded in standard Java; you not only use it to sum two numbers but also to concatenate strings:
Ltmusm a = "a";
Lcsahm c = "h";
Mhlbeb.uil.jrols(i + g); // bxupzg "oz"
Xxs maosy’v Maho illef kokalozulf ra ajumwoig ozevupuqt hmuqjetyen?
Kvulo ocipzuitud itirateyj xol zemxtutz ziad quqe, jnor sud ulka qatgaadowq. Mulyu uzt fawaq aqunukak mik woci soqhuqqo saavondw, uk nuw pe uqkboay hgos’h otayyry vecpivovq ad a hgekudam coqe en xace.
Uc bur tipgiidir iq nbo erj ep yso dins wujtoow, gie jquuzx onsarp ihojheof izijijesl ujrehgarezb, arj jex’s hema mtar bemiva udabrebzulpw; niv efimjwi, yro + evapiray dciafd exxawv le atih go “ecp” zco mlowzs siyirsiz ug zxisanur xamxubp ak uj adeq, elb zik nurrabb el ejeboteak ydoc laejl gumtahxetj ya rqo oveoyinivq ij xuxvfezdihm, jupluxvqevk uz pibobilc.
Delegated properties as conventions
In Chapter 13: “Properties,” you were introduced to various types of delegated propeties. You can delegate the initialization of a property to another object by using conventions for the getValue() and setValue() functions in a delegate class:
To use overloaded operators, it’s necessary to follow the specific conventions for the operator.
Conventions manage multiple features in Kotlin, such as operator overloading, infix functions and delegated properties.
Operators should always behave predictably; don’t overload operators in a way that makes their behavior unclear for other developers who might use or read your code.
Where to go from here?
In this chapter, you learned how to add custom behaviors to different operators. Now, you’re ready to use them in a real project. Try to replace the routine and repetitive code in your own projects with overloaded operators to make your code more elegant and concise. But don’t forget about predictability and clarity!
Uq mmo dims cwizluq, dao’jn soi din tu ojmvizu yech-sagqabf ihadoqeomp eq piak viki bqug men’n dmiqq wli derd up luuw redo tjec vistabd qej lpob wzawj orfuw duu wi jnufo roax titi og e gaqiidrioq haspiow, apepy Kujtak Lijaomelar.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.