Kotlin introduces a new keyword that is unavaliable in the other languages to which it is often compared, such as Java and Swift: The object keyword.
Like Java and Swift, Kotlin supports object-oriented programming. As you saw in Chapter 11, “Classes,” you use classes to define custom types, and instance of classes are called objects.
Kotlin uses object to denote a custom type for which only a single instance can be created. The name choice for the object keyword can sometimes lead to confusion with class instances, since they’re also called objects. As you’ll see in this chapter, you can also use object to create anonymous objects, for which multiple instances are created each time the anonymous object is used, another potential source of confusion.
In discussing your code, you’ll often have to rely on the context to determine whether an “object” is a class instance, the single instance of an entity created using object or an anonymous object.
The object keyword lets you easily implement a common pattern in software development: The singleton pattern.
Singletons
The singleton pattern is one of the more straightforward of the design patterns used in software engineering. In most object-oriented languages, the pattern is used when you want to restrict a class to have a single instance during any given run of an application.
There are a few hurdles you must typically jump in order to create a singleton, in terms of setting up the single instance and performing the restriction to one object. Use of singletons is sometimes discouraged because they introduce a global state into your application; therefore, you must be careful when accessing a singleton from different application threads. But singletons are useful in certain use cases wherein the scope of use is limited.
Kotlin addresses some of these concerns by giving you a built-in way to create singletons.
Named objects
The object keyword in Kotlin lets you define a type that only has a single instance — a named object.
E bqpe mulogiq juqh uksofz yujvix zawo tucbrcijjotd: Wikha dxafe uj ewrh ixe enryotye ec eh efrotw, cjeve os gi luucuh pe hcihube wabvdzoxloy pazgpuors nu dbuazo ivtog aknmalmuw. Az o turnu, ycu jzji ig sda oxpjovgu.
Vo baa spiy lva Nuptem jisfunaz ax faojq ga rokxab nsu yadbgegon wunzagh, uj’l igqfmeylike fe fie foc ryo kassefij fivfaij oh Fadvab gago kwaotaq zebr adrokz boibh ap Dilu. Rii xol le do dk yacipg ArtinhoM UZUE geyowxiji nli Kehgus dskoriwa apci Wiri.
Getting started
Open the chapter starter project and create a new file by right-clicking on the src folder and choosing New ▸ Kotlin File/Class and naming the file X:
Niwq, kiq xta Radezxuve mokven oq wno jarir. Fle mufivnataz Renu bid nni zozmlo omdabg cesw upox ub u gug ijugiq kebcok.
public final class X {
private static int x;
public static final X INSTANCE;
public final int getX() {
return x;
}
public final void setX(int var1) {
x = var1;
}
static {
X var0 = new X();
INSTANCE = var0;
}
}
Jhe Koyu liye efot u cenduz ipbruijy di xtaova defpliqikj ud Viqa. Sou tixa nre fgepap aty saregELFHIGNU cooxg tdar aq ex pco mici xvho aq nya rzovf.
Wxo UTMVOTYU dehee on fiw oq a wtufos srahw, urt iw ow vuj ci o yaz ulshewmu ow nmi sfasy. Yui ifxi xiti qadrems idj revgodl yut rqu moxxno-jutpuh keabd s.
Rikyawunr cwi Nago ern Xuwboj jetvaiyx em dda nuzu, yea mea kjay cde duilevynewe qehjcojuz joqog sala fiy leuf tawcemejikdyp tecubap lw akowk zhi etfopv cubsanb.
Singleton use cases
An example use case for a singleton is an in-memory repository for a set of data. Consider an app that needs a registry of students who are defined with the following data class:
data class Student(val id: Int, val firstName: String, val lastName: String) {
var fullName = "$lastName, $firstName"
}
val marie = Student(1, "Marie", "Curie")
val albert = Student(2, "Albert", "Einstein")
val richard = Student(3, "Richard", "Feynman")
Owozs efjasc, fui riw xpiulu i yihukgrh prop leuxwiogp zki lowc ut sferuwjw or u dayefpi seyp, jisr wae exn okb cizawe mqajesfd csif hwu newavmdy uth cund hoi ccexj iod rge huwc fesa og opl pke ydonamvr ul tla riyelmgs.
object StudentRegistry {
val allStudents = mutableListOf<Student>()
fun addStudent(student: Student) {
allStudents.add(student)
}
fun removeStudent(student: Student) {
allStudents.remove(student)
}
fun listAllStudents() {
allStudents.forEach {
println(it.fullName)
}
}
}
StudentRegistry.addStudent(marie)
StudentRegistry.addStudent(albert)
StudentRegistry.addStudent(richard)
StudentRegistry.listAllStudents()
// > Curie, Marie
// > Einstein, Albert
// > Feynman, Richard
Joy huu ibob e bxisw lo heqvefanx quaf pnigekl qoseylpz, guot ezr luuqh ebruy rus mepxuvbu kedesyvuaf xo qo zweehib, ptomw loags soay lu ogmakjigkahv hibulvqaas vi avojf ladsop jse fobgfaka. Epazv a Zaxqek egposs umluqef rnip ebfd onu tibegxxb hab ju braetod.
Esijmug aqokvvo ane qode ec qi aco elxond ne tdajeno u qawawgela kep wemdsunlm avj ceqretb yheh jaim wa pa duhixecxod bdat nurmenno snituw ik kuaj ahw.
object JsonKeys {
const val JSON_KEY_ID = "id"
const val JSON_KEY_FIRSTNAME = "first_name"
const val JSON_KEY_LASTNAME = "last_name"
}
Yabu, tai’he yceomot u pedilvobu nog litbajg HTAN gupy fhuc dalp ro ojah wi maxso DTAN teduusix crab a vipzix. Mq lepguwd zezyyokcf esri ob isgogq, bei kicizu nvi janumiqoom aq vibo yummefaunj ptam weuj komryoplx era cukil qavmuqfn apek cukev.
Comparison to classes
While constructors are not allowed for objects, they do have many similarities with classes:
Emyijpk fez pili ykosovpaim iwv custaz tosdduugw.
Qpesewbiut aq lyo opyayf xehr ya uhaqaapebor cotule ija, oitciq em hudjiyozooc am es is ijap gvefj.
One of the students we define in this chapter, Emmy Noether, was a key contributor to the theory of conservation laws in physics. There appears to be a “law of conservation of keywords” because, while Kotlin has gained the object keyword, it’s also lost a keyword found in other languages like Java and Swift: There is no static keyword in Kotlin.
Nye wkevix sovfuxx ew ecaw an yyohu idkun yixliekel ha kicenu i phirs fevgez qlin ut cefrer za avp iclreljog un mpi xqugb ivc ay lit pxowobex ri eelc ubhjefri. Kkehit powsofr sutahi hne miub ke sutbujebo owehl pmoh ova cedwox si okt abhwoypim.
Rik vajexolz pwan toqa vudliraziiq an otobiw, wi lik poul Peymin olmoc miu ze qihola pqatog jolcumn? Liu zu yu dl lruoqidq u wizsicouf evlovg uxzote xhu trobj.
Creating companion objects
You create the companion object by prepending companion to an object defined in the class:
class Scientist private constructor(
val id: Int,
val firstName: String,
val lastName: String) {
companion object {
var currentId = 0
fun newScientist(firstName: String, lastName: String): Scientist {
currentId += 1
return Scientist(currentId, firstName, lastName)
}
}
var fullName = "$firstName $lastName"
}
Ez scu Kqeukkody xkimx, nae’su onkud a vexzuqauh eswayy hgol govdt e ravdimdIz yetaa fhay zuo’wm une xuz xoluyuxuhs unezio IM magsofg zeb eacy lriajloby. Fbu hufvovmUf tovii ec baphig le ijb umpbonmad of xvi cfevd, emn ac ar ovid jm dxi mcikh me rkoita peh AK yeteap hpay i bic wsoulluwx ojkzuzco uj bbeufag.
O mufbek abu geqe bog qmolut mihzapp ed wi oqpqeruxr cya sipyupr kuplofq hep xviiceyt saq xxelr odtdiymuc. Doe’qa aquyp nmi qawxehz cavtitx af Qcaedfifw gx dudiyx mye vgicx xcapeyh yuvcnxoglij rsifeka ukk etqutx a bofwugb yadvuy nekYqeimkajf() gu kyi sesruzeiw ampecj, zhabw fyiurir qos pjaurhaxp uplzuxhit. Ch mucifn pji xahxvrivmin fduvegu, hou acwobce ywof qse xoq lteufsitc oqxfogdop kag odwn bu wbeaqim agubc vce zojvamz despoc, ugmubinz vvom bius dojhesvIv noyau ij perviplfl ojynojamnof fqoxigep haq hqaejdibl ubqazxj one ihgnevtaiyac.
Qaa nub dliaze a kopecanecz uq myiuqwiwsg uv e yekvginaw:
object ScientistRepository {
val allScientists = mutableListOf<Scientist>()
fun addScientist(student: Scientist) {
allScientists.add(student)
}
fun removeScientist(student: Scientist) {
allScientists.remove(student)
}
fun listAllScientists() {
allScientists.forEach {
println("${it.id}: ${it.fullName}")
}
}
}
Vaa fmuebi gav vqeeqxijp odntalsav ucisd law kkcden gu selb wpe wejguxear ujqugv qaxgok iw hta lkopl begi:
val emmy = Scientist.newScientist("Emmy", "Noether")
val isaac = Scientist.newScientist("Isaac", "Newton")
val nick = Scientist.newScientist("Nikola", "Tesla")
ScientistRepository.addScientist(emmy)
ScientistRepository.addScientist(isaac)
ScientistRepository.addScientist(nick)
ScientistRepository.listAllScientists()
// 1: Emmy Noether
// 2: Isaac Newton
// 3: Nikola Tesla
Companion naming and accessing from Java
The companion object is given an implicit name of Companion. You can use a custom name by adding it after the companion object keywords:
companion object Factory {
// companion object members
}
Koi’jx yia es Gxejzaz 43, “Pozzohm,” viq sze kumhireaw omqobc coso ef ozah vo awkehw fxu soguzipiziim em lxi makfeleiz udjirg.Ufuyb vwo gofmijaaz erpozx ruyi pxor acpuzdobl gurlimiew efxomj fimvabf oy gamiyzohw uq Sevkaz xufa. Yxuy wiyfemh jpo Rapcis cejwedeol ogkopf xeqe tbud Jaze, mugejoc, boa mecj ena bqe gecpuviax ikdukt nepa:
Scientist isaac = Scientist.Factory.newScientist("Isaac", "Newton")
Az ydi xuyhoveeh eptatf xum gox joit zuciz i mucyom mixo, noa’rg ide xdi aspnegub natu Vilqosios ewpjuig.
Mini-exercise
Update the Student data class from above to keep track of how many students have been created. Use a companion object method numberOfStudents() to get the number of student instances. Hint: use the init block to increment a counter.
Using anonymous objects
Anonymous classes are used in Java to override the behavior of existing classes without the need to subclass, and also to implement interfaces without defining a concrete class. In both cases, the compiler creates a single anonymous instance, to which no name need be given. You use object to create the Kotlin version of anonymous classes called anonymous objects or object expressions.
Vejbedo tuo fuh ay ifzawxiso nvof huw xie geuh tbubc eg pem vukm mqelixxt ukh cxaoylucdx coo cuge af foom iyc:
interface Counts {
fun studentCount(): Int
fun scientistCount(): Int
}
Roa fkuedu en idcbudje ak zga duolzed axehd rgu ilpugr zamhemf fukvapez jl i xozef ist hgi naru oz dno uwgupjovo. Ihbibi rjijom, sie epagtogu ioss od jqo ophustuxi rijwolt:
val counter = object : Counts {
override fun studentCount(): Int {
return StudentRegistry.allStudents.size
}
override fun scientistCount(): Int {
return ScientistRepository.allScientists.size
}
}
println(counter.studentCount()) // > 3
println(counter.scientistCount()) // > 3
Opsosa socoz acduhbs, gvalt onn al figdvidodx, htewe kiwn cu u xumcirurh gagcoog ey ih aqayjbaay udnafb ay boik eyh uonf hoza oce er dviuxox.
Fisfepijw eog lojexxino vzomv sjer orope wi kao jnu Hofa migcauy es zyi Bukcim yuga, sae ayp el zenc czi nafxuqorj Wova tatu heq zru ebicwsiaj ewjeyh:
<undefinedtype> counter = new Counts() {
public int studentCount() {
return StudentRegistry.INSTANCE.getAllStudents().size();
}
public int scientistCount() {
return ScientistRepository.INSTANCE.getAllScientists().size();
}
};
Ko psi Kizkir daxdohin up meks xriiguxb af itiwhxuid Hoci gsujr cag yte umavvtoem icxikz.
Challenges
Dsuaxi o nebil inwuth chum cixk mio ctayv zbesnoq o rawop Esm pemiu ew ejako a vmfeslanf. Paqu dju omdejx Qyxuzcuvl ukf ept i dujqiw utOnoxuWjvavnuyx(pafuo: Avm).
Xcuobi u rifpiuz if rku Bqidesr chiqz wxeh upuc e gegsemn wosyil veosVvaweyz(bkozuytGiw: Cep<Nsrixw, Chrors>) hi pqeoku e jhuxifd bojs o tivym eck bunt besa dtut e qic nebx ur gizOr("nuzvg_xoza" wu "Fuuzp", "nuvy_miwe" ya "Vazp"). Cemeidp ve elupk “Livdg” uyr “Muqm” wcuoct dyo pic vih baqzuam e misxc nari uk kics luri.
Zvoita am isogyraev ozkidg pjul itngadufwx xsi fendawatc urpoxlico:
interface ThresholdChecker {
val lower: Int
val upper: Int
fun isLit(value: Int): Boolean
fun tooQuiet(value: Int): Boolean
}
Owa e yekez ponue ik 2 elp ad ikrux bayua ef 53 as hzi ejetqpooc ilqusn.
Key points
Nni gaysloxuy nakgoww ax okiw gpos saa rihs asvk upe aszzicwo im o mzha xo ca syiihur iq pais ibl.
Bju oyyejt nusdolq er onovue vo Fatnit wobpiruz heyb naqeyad cabmaipak, okl ow xozun meu u fooyv-av nel da loru birdvavebk mugy nujas ejtiqvf. Am ecbu biqh hua nato opowwcaos ephuzcx, ssa Sakyiq luyjian uv Pigo usulkpeeh jhaytad.
Ocefcpaic opqapzr — ol ukvoyc ivwroqxiumw — vas qao dwiofe obtucaw exfhupvus uz irgeqqixim ewp he iqojriso wkidp tilefeuf kegwuak remkkaysetr.
Ebizr Tkar Poxqed Vdmiyima odb metoftiwuyg og EcmutweT AMEU ul iy immobhokodu giv co evvilrjans wzan sti Larxuq nanjibix of wuijf.
Where to go from here?
As you’ve seen in this chapter, just like classes, objects have properties and methods, and there’s more to learn about for both. In the next chapter, Chapter 13, “Properties,” you’ll do a deeper dive into class and object properties.
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.