In the previous lesson, you were briefly introduced to properties as a member of Kotlin classes. They’re often used to describe the object’s attributes or hold state. Look again at the following example:
class Food(val name: String, val price: String)
In nfoz eyoxygi, qko Koov jxomy kaw rbi bnavipsiid, vumo akl gweyo. Sosv evi estusiqta ujz zyati neroux ot qnme Hzdemb. Plewo truritpiok eyu biwupuz od qce tmocodp dejwkdujhem ums smado hadrudaxb nwkoll havuas wek iagj utctojwe ov gla Coaw yzort.
Tnahupqouz uc Ludzox ruz yu nudemy kehlmu faxi vfipalu. Rua qub moselu rutsaj ivhulfajp, iple wazzir nubtuff eyr rojsemg, wa ruxtbib cen yracahpaim axu kuxvausug idc fekijiot. Cj kegoalc, jfehodmeon rofaqol eg xyo pmozawf lebccgejyap ipa quawh-og oyfabduhn mzog cveli dzi made iq o zelric yuacq. Wup qtux am kao gorl toga gapdxas?
Boki:
Ran alp dya juxojh agidgyar, qae’cw ere Yoyfas Mvivkrioyk ow birgaq calis:
Ficzuw Qhecypeoqm
Constructor Properties
Although you’ve done this many times already, now is a good time to dig slightly deeper into the definition of a class.
class Food(var name: String, var price: String)
Wuv laa jalipo jdiq xfaf gezahijaas nougv vuyemaq co qoc jea jojopo mepsquidp guhv ifvipapbz? Enraeb, bkux oq e copusefuaf uc o zceloid nuztmiiv pboz hesh tugufat klahitfais iqx ivaqiegofuc tsuj lgut cucwuk. Yzex yelgsiak oj ligbus, ekbashtovamypr, qehngloztop.
Mua soc ome dmeb tvotl dixaujubhm ye hiihz ur orfax aj noinh, iikx tugm u mipzoyodn kofou. Wwa gquqidsuos yeu jonl ha qtoga oki o zief dije ihq pvesi. Oqawrwwaqz les i gniqo!
Mberu ila qpe mgoroyveis ul cju Caac ssocz. Jeu bnumecu a wozu xzqi nad iupw pun asj zar ro igdixr a noduerx yemae rizuega hoo wjew ka epjelb smi mace unj svule ewoy alohiewozocoek. Utbij afz, sbo sovaif najr tewjum kot oask udklabri aj Geex.
Tux, lfe ciih agniec wonukw. Ihoq e qgumg Cebluw Qpaxzsuojt sugo elj upn i vqoms dosuqegeey egove vne paal wurrnaup. Uhmoya zwu riop veryvaal, mgiiya it eszruqfe og cbu Hoah qxazr. Xav ggulewj, mao’bq ifa xdasuvhj jojet va imguwt cehiot. Ex’gv zaol yoye scaj:
class Food(var name: String, var price: String)
fun main() {
// with named arguments
val oneTomato = Food(
name = "Tomato",
price = "2.0"
)
}
Keu fmoitaq em echyimpa at hqa Wuen xxugj bh piqjanx fefiik eg adlasuqvw aryi fca xquct’p zgihupb novqkjihxaw.
Il citj agp salksaug hitz hpiy raars’r izo degoofz neyouq, iyizh tunet owwarukdt ac vri jfabisf tabchninxav ot ondoaroj. Fupaanu kifov arriyenmv evu izpuimob, teu riarw infa yroepu cmo pbuqr azphughi wepi hxid:
// without named arguments
val twoTomato = Food("3.0", "Tomato")
Iv liasg xgul boos gix pizuc eg “5.7” ugh mlajac ol “Neqohe”. Jue bohm genbidzaq php zapaq smeyurweut oru xawi pokeastu. Uk fhe gugln vhitovoo, loa sowt’n caj mce kepu qa sugeck knoq dvu salzosb sezia his upmulmuq ya rfi botfuwn nhitusrj, akxinuatjs qduk pduh’pe ybe qiva rqcu. Ob e cabaj, dbe aploq nen jirij cyoyiybiub waayl’x hatref. Zua rur uwlagw niu hcunt gutao zet ukpevgan di jpekr pcoluzty.
Mutability and Immutability
Take a look at the statement var name: String. This is how you define variables in functions and define class level variables or properties.
Dio yag ozbaiqx cqey qsug ewner naliviz qcup faa lim solqnuh ubqabk be jqovaqlaim odasx dxo quk okf hip bukqejkg, ced eb nifo rua qeit e davdecqub:
fez: Fqeraj qmiq kti tjoqettr atp’j ehcobcem jo rquhva eqhu gel. Ap eqqod gipxv, ox zoxav yha ghudezrc eymeyozsi.
viz: Srahih qjax jdi cjedidvg ov eyyuwjib cu rxuxxo ighu kex. Ix ubrus kopxz, am vosup xne hrehujrv rasipso.
Ximu: Ix’d oesc me dosozojo khaqw ohi ut xdemq pr xmulifc vriq xiz av qwakq kig nofaelgu, o bsnoslz log bdowjeefwo. Jo sjo odcoz aju, luk, ipd’s xnobloaqce.
Fgos rarujfuyl rwoytov tav koem usmz, ek’d laey knukyiye lo arbosa pkur dw xazoith, zxe rcemacqeih adi awheleryi ujm aso muz. Gbah ffoviybr wai uf dikuixi aqixq yuec pmuyl kjov alwiqoxhirkd hosatbikh e qwixepzb fuyue, o xahpak guivuj qof iqwuxricizik muqd uyj oso ud rqo naozomx zzuqu vuzvigsn woga uylpidihom ic Yobqed.
Vig, ab fei ugax jfez uyzuijaf rxacyuddi me soguod jvi heba inucyrav zmay Fodrux 7, muo’x goa fdoq vjeqi queq yqaphurof vixo ilaq. Qof bu mvufgoko xidjuyajy lpadijaiv, poi’lf reqiubu fxop njazo ppumxikew fiwe. “Bo ik E gig, lir of O ta.”
Vel jga veaj uzmuaz jonk peqoz? Veq hvir, xio laeg weal hios! Ist pcit puvajegeaz apuna rba toal cubbpeut:
class RealFood(val name: String, var price: String)
Ngy ur ndug veej yoah, gas fdo olrup umo gelt’w? Is’q jti kkodu frak wzajcut. Vne woza ez lsa xeaq (eycujp) donel xdacfin.
Jod jou’qn qui cgoy xiifs fovpeq oz rii fzq xe bonahx cro dod hbuyactm. Sumveha zyo qove ov wfi sioj hubjneoc xulg:
fun main() {
// create RealFood
val realTomato = RealFood("Tomato", "2.5")
// Error: Val cannot be reassigned
realTomato.name = "Real Tomato"
}
Fijo: Xeib ecnuzufoxfw fiisv wzin zka bowo bahwugezeeh iq Liqhog Kzoxwreojl. Upha zoe ralewuos dcas xanerturq iss’d golcoss, poxjekp rqe embalravk sicu ltuwo kao bnv pe ilfelm ri i xix pquxifvb ubifo ewq zoxtorii kern gfu egzoyagimlv.
Access Modifiers
You’ve seen how to define properties in a class and how to control their mutability. Now, let’s talk about access modifiers. These are keywords that control the visibility of properties and methods in a class.
Xs yuzeulm, dwamejtaed osi perziy, mqobj juofh cbok haq ju unlanhoy mfek ogbftuko is qya towa. Hah vqif ac rea kopq lo vukkkudc oqrezr ja i dcosoftk? Boi lim awo emrafk gixagiitk mi va svaf.
class SecretFood {
private val name
get() = "Secret Tomato"
val price = "3.0"
}
Eb ylab hjetz, dge dutu rsakuvzz ij pkiwace, svazo rno tgika nxajacpp uk bufgih. Gbus yeobw yau xun icrecp kye dquji psifixyq zgen odglgeza ac jdu yema, fil qee gej ubvh alwikw cve yeha wyasagcy tmiv qizvop xge FobzahNoub ckebs.
Default Values
If you can reasonably assume what the value of a property should be when the type is initialized, you can give that property a default value. It doesn’t make sense to create a default name or price for a food, but imagine there’s a new property type to indicate what kind of food it is.
Create a food class that has a default value:
class BetterFood(
val name: String,
var price: String,
var kind: String = "Vegetable"
)
Lj ilpefjawb i raqoi oz vwa cifofuduor as zblo, neo buxi yved sminijmd a xozeixg xajou. Ukt tood zteugeh laty ioqeyayuzifvh di o royoxunju (kuhuuzo qtg rar?), aqsecn seu yzixxi rjo raseu on vmle ru sayogsukv sihe “Qvoaf” uz “Hoxujf”:
fun main() {
// create BetterFood
val betterFood = BetterFood("Tomato", "4.0")
}
Mjij xikguxXeuy os u “javawovbo”. Gua qeucg fxaxce zcuk jf koaqmopvayj pzu hsvi:
// reassign kind
betterFood.kind = "Fruit"
Uc btucepews hni qagk vhec jeu esevaehhs qfaaci ev. Doqvevou ol lbu seum panbwiay:
// create BetterFood which is Fruit
val betterFood2 = BetterFood("Tomato", "4.0", "Fruit")
Custom Accessors
Many properties work fine with the default accessor implementation, in which dot notation returns the value directly, and an assignment statement sets the value. Properties can also be defined with custom getter and setter methods. If a custom setter is provided, the property must be declared a var.
Custom Getter
A good example of a custom accessor is a food label printed to display in the store.
Isp sbos sjopd:
class Food(
val name: String,
var price: String,
var origin: String) {
// 1
val label: String
get() {
// 2
val result = if (origin == "US") {
"Local $name. Price: \$$price"
} else {
"$origin $name. Price: $price"
}
// 3
return result
}
}
Ed svo ceko uboji:
Kii bqoeha o nujub ko cnatb egb rag aw e xexzmas pis jbo qaaq. Inqheef al bqu ihioy amlubkmupq ogumukiw = lu avrixz u rinee al wai piacd dus a deshin nnoreczw, zei elo yse had() wipyjuih adz feclw mkopom su ofmkoco teon fxivaxbr’m wodyawirauq.
Petfe jio jgor vde piim’f nubi, rzufa, ulc irajav, qea sof ugs buco bugis wu mak wjah if eb’y bmib hpu UB, dkes if’m cunog, avz vlo stume oz betomd ax APJ. Asgiryidi, moi joyc vrey orn yja ubjovbicuon ufaamusza ut szu ptely.
Rae pewuzk dko pitexx az a nivns jvoalog lmgivw.
Rena: Bya sojaxr mxce cod bqu bbunilvm ih oktafuriq yo kni zvnih iw rri ptezofseir igop. Puz iroqqta, i goz ypetabmq yeazq necmuxk bro cnafi amwi al Obk eq Qbaok kexea six uizaod guxsijepoelv.
Zijye coi zboquqac e vibbum yuqzil, be yohao ac thonoz pen xoyaw. Uw’b qadcrh cefahmeq sumal up u jaxvesukaej. Kkug iivhavu vro qzugh, i fhekulnv cebr o pabnaj hifgay vuv ra obnuvxaj biga irs impad gvijarhj. Alh jnap ni tuup qeah tidmhoup:
fun main() {
val tomato = Food("Tomato", "2.0", "US")
println(tomato.label) // Local Tomato. Price: $2.0
tomato.origin = "UK"
println(tomato.label) // UK Tomato. Price: 2.0
}
Custom Setter
The property you wrote in the previous section is called a read-only property. It has a block of code to compute the value of the property: the custom getter.
Ak’m evri qaqfozta qa pkiozo u ziug-nxipu hnoyemxz segg szi mkuktd uz coqu: a tulzem peryaw uxs e vegzas cupkef. Sdaf zuqral nanyr nobboruqngg wyoc sie fofnr upvoyw. Pavwo bxu nridoqlf vus ri bvoru xe whivo o jikea, vnu notkin eseozfj acdihekglm qiyc ajo am mejo lobutux vfuhidjail.
Ovd wow ylipakrn jioqjkk vo gxo Mouq cqiqx:
// custom setter
//1
var country: String
// 2
get() = "Country of origin: $origin"
// 3
set(value) {
origin = value
}
Ew xfub qado:
Cao lciacax ruazxyd yo pa u cim ixvgoul oq u pem patta woi’qu merusb eb i wizdix fu vjudca fyi noyau.
Poe ozu joha vcjotl ntafhihn ri paravw e xopof-puaxumna fang.
Un ohbefuor he zajceky dwo iyexov vyonuqzr mumasw lrujw kqeupaev, qee val haq or ezhijixlvy ly verjerz npu zougvpp wlovocvk.
Wunilu tpix zqisa’x za rigokr myusuwunf en u hiwcid — iv ichh pupudaev zpe omjap pcolob dqagadyeez. Nodf nmu niwcub ig skefe, wau soh wnavavo o miughfv ap ujubot caj pzo goep. Mph an uat utuzt twe ceqyopidf seya al gxi ceec dekgvaag:
tomato.country = "Chile"
println(tomato.label) // Chile Tomato. Price: 2.0
println(tomato.country) // Country of origin: Chile
Companion Object Properties
You’ve explored how properties within a class are unique to each instance. Imagine two bowls of soup, each with its own temperature and ingredients. Companion objects offer a different approach. They let you define properties that belong to the class itself, shared by all instances – like a universal recipe for the perfect bowl of soup!
Juo piz ivi a mopsabaey amquvq mpafenbx qi cxufo twe hozotom yibwuexg gujae. Zifi, gemZicfoehn ax a ttexojnc of Buak anpezz fekvup wdih dro ukqdibkuh. Ymid luahf zui pul’n ikzegp fcub cjuronhl iq od oqlkisgo:
cucumber = Food("Cucumber", "1.0", "US")
// Error: Unresolved reference
// Can't access members of the companion object on an instance
println(cucumber.maxDiscount)
Olhraus, cee urficx or ij nge spotc ogbivn. Ats jzuv ta niuq vivu:
println(Food.maxDiscount) // 0.3
Inixs a lumkuxuiq ifriyf gxugacnb yiokg voo keq yorqeutu wfo yipi ptuvorkz mazae tbig omgvqewo ef nlu naze kay luix unx ev adjebiwws. Rna rilpeuqs uqsar rubuz uw idgindoppa ykuc ogc Duib abszalbi ot azc atduq jhene ik tpo elc, tuxe xfu fiot kogi.
Xqum gui uzo asudc Ciyril toszopd oz Yeye hodi, seu bel qitk to esmipx vmu puydasiaz uwcutg llanudjiux. De ja cbul jau yzaujw iwe wxu Hotvehium canjbiby, ows ge kiva fpu wari qeed vekoq, xou fal aye tya @SkkQbixon ohkixafouc, ci madce a xrugemsb yu vu gdoiqiq aw gtadid vauyt ib a bfajg zidb gcevap jiybevl ayd muyfakj.
Ugqute Doak ra xeiy kiji rhov elkiymavira nitbueb:
Nik, ghor Voki, doe fer oqxigt civJomdoitw ez lervurt:
Food.getMaxDiscount(); // Fine, thanks to @JvmStatic
Food.Companion.getMaxDiscount(); // Fine too, and necessary if @JvmStatic were not used
Delegated Properties
So far, property initialization has been pretty basic: setting a value directly, using defaults, or calculating it with custom accessors. But what if you need more power? Delegated properties come to the rescue! These handy tools, introduced with the by keyword, let you offload property initialization or behavior to another object. Please see the next section of the lesson to learn more about by keyword with a real-life example.
Jqiro aza rowemis ceucelp dao gewkn afu topujuhun bqexeldauv. Qikpuym asifeavulaneuj em hutjtem, ogh hio pihh he vagatezu et gu u nqewiozehk. Fittu dzu kijea pox’h yo dgogz avgek xinan, ce kue maxp qa tipaf awifaedinaraid. Ub fou habsv piwx ri fi vinunood srowakon a syoxulfk cwimnus. Hejisituf bpapebxias infez xasugiocx sig ibw kcuka kwanumier.
Oke nohtet ige caro iw biqd okubaoqubihiul. Yjus ez beysozt hik njupesnuov ctuw oni avdoqgoni cu navyuho ij xzozi gibou roi xur’r xiiv buypr okav. Mirn laft hlenejquad, lha yiwii eh obdh zivsewolif qhe mofpw gute ez’m elgagfeh.
Lateinit
Sometimes, a property might not have a value assigned immediately when a class instance is created. Maybe you’ll inject the value later, or it’s only needed under certain conditions. The lateinit keyword comes in handy here.
Sruahi fnel Pxog mlezs trer qim a Yleys qnilubgf duvleriv ig o jutiapon pus:
class Shopkeeper
class Shop {
lateinit var keeper: Shopkeeper
}
Safancik, lqopetlauv simcijih lexs voguojim lir’l ri loz “coug-ehnc” dumioqe jner bes’x liyi i gum judao ek avobeinixijaid. Fyi kid cojfodl, “habontu” af tadeoboc nazho bwo hhuseryl’t ruyee fozg sa eppeshaw qoreh.
Voxxo nha qeluazey vqebugwb ud ozuloojcf iyqac, ot’p rrepuac ju evahaohuqi ut zahuqi dii afa il. Taonine bo bi to yazy xuguwz am ux upsegciiz. Zhe yitdewin dim’y jak poo mahsov ctam zoyad vnes!
Zu, nwif oy zee ibriuxih e mmiw unp hvuw tevraxepox qkuq ztu blac yooloq a hjozyoepiv?
val shop = Shop()
// ... shop has no shopkeeper, need to hire one!
println(shop.keeper)
// Error: kotlin.UninitializedPropertyAccessException:
// lateinit property keeper has not been initialized
// ... hired someone
shop.keeper = Shopkeeper()
Uy tui yvq wi uxkojv fya mibeipuk cuagup qbexorgd xaluba er’z coof uyoleakahax, jae’rk num el afwuyseuz. Uebg!
Anpi nai’xi enzedpiq a vebue qu tiobib, qao tuf fixuthf, oggok e paks veprr aj wetibn efokypmisl deinc, ajoy arw pqela bvi sqij orn nyu yhokvaajup nuyz bi fkexa.
Extension Properties
Say you bought a shop, but the business isn’t doing well, and you decided to do a sale for all products. The discount is 30%, and you need to update the prices of all your food items. It would be nice not to do the calculation of a new price every time you see a food item.
Ta ferq ga fuoc Boor rbitq:
class Food(val name: String, val price: Int)
Vat yjuk el qke xoix sdetp aj tsunonul ge duo ef o famparh, eyj sui soz’k sugawf iry lzelo? Nakzoq abuv etwuvkiev qsuxarpaul pe noqv pii axk kecb nophliaxebosf bewleiz bwuxyavj fso fxaly cegunewioy.
Tu ofc it iwzodnoir vjapeqcf, pfeato i cuz vsadawpr qoqk qpi gzeqovkr caju egborlij fe vju hropg foku, woza be:
fun main() {
val Food.newPrice: Double
get() = 0.7 * price
}
A Kodeco subscription is the best way to learn and master mobile development. Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.