Kotlin object keyword - mariamaged/Java-Android-Kotlin GitHub Wiki
Kotlin - object Keyword
Most likely, there have been developers over the years who have wondered why object-oriented programming languages do no have any sort of
objectkeyword.
Singletons
- One way to declare singletons in Kotlin is to use a
top-levelval declaration:
class Transmogrifier {
fun transmogrify() {
// TODO
}
}
val QUASI_SINGLETON = Transmogifier()
- In truth, though, we can have as many instances of Transmogrifier as we want.
- QUASI_SINGLETON is merely a global instance of Transmogrifier.
- We
cannot preventothers from making their own Transmogrifier instances, as then we could not create the quasi-singleton.
- For example, we cannot make the
constructorbeprivate, like this:
class Transmogrifier private constructor() {
fun transmogrify() {
}
}
val QUASI_SIGNLETON = Transmogrifier()
QUASI_SINGLETON.transmogrify()
- This results in a compiler error.
- To create a true singleton, all we need to do is:
- Replace the class with object.
- Call functions on that object based on its name, rather than creating some instance ourselves.
object Transmogrifier {
fun transmogrify() {
// TODO
}
}
Transmogrifier.transmogrify()
- An object declared this way:
- Can have properties.
- Can have functions.
- Cannot have a constructor, which makes sense, since there will only be one instance.
- However, if it extends classes, it
can and mustcall the superclass constructors.
class Base {
// TODO stuff here
}
object Transmogrifier: Base() {
fun transmogrify() {
// TODO
}
}
Transmogrifier.tranmogrify()
- As with singletons in any programming language, though, the ones that we declare via
objectwill live for the life of our process.- So be careful that you are not creating a memory leak by having an
objectholding onto more and more stuff over time.
- So be careful that you are not creating a memory leak by having an
Companion Objects
Another use of the
objectkeyword is for acompanionof a class.
- A companion is a singleton, associated with a class, whose functions somewhat fill the role that static methods do in Java.
- In fact, if you set up those functions the right way, they
can be called from Java as statics methods.
- In fact, if you set up those functions the right way, they
Declaring and Using a Companion Object
- A
companion objectis simply:- An object.
- Nested inside of a class.
- Then, other parties can call the companion object's functions as if they were "static" functions on the enclosing class.
class Thingy {
companion object {
fun something() {
// Do something
}
}
}
Thingy.something()
Um, Why Bother?
- After all, we can have top-level functions in Kotlin:
fun doSomething() {
// TODO
}
something()
- However, companion objects have one key advantage:
- They have access to
private functionsandpropertiesof their enclosing class. - Even though count is private,
doSomething()can still reference it, sincedoSomething()is part of the Thingy implementation.
- They have access to
class Thingy {
private val count = 1
companion object {
fun doSomething(thing: Thingy) {
println(thing.count)
}
}
}
Thingy.doSomething(Thingy())
- By contrast, a top-level function cannot reference private functions and properties so this fails with compile error:
class Thingy {
private val count = 1
}
fun doSomething(thing: Thingy) {
printl (thyingy.count)
}
Naming a Companion Object
Sometimes, you will see a companion object have a name, though probably not one named after after a companion.
- This has limited impact on your Kotlin code - you still call functions on the class as before.
- It does have an impact if you are going to try using the companion object functions from Java.
class Thingy {
private val count = 1
companion object AmyPond {
fun doSomething(thing: Thingy) {
println(thingy.count)
}
}
}
Thingy.doSomething(Thingy())
Nested Objects
A companion object is just a specialized case of nested objects, where we have "singletons" declared inside of a class.
Object Expressions
- Frequently, we need to:
- Pass an instance of an object to some function.
- Where we need a tailored instance of the desired class.
- With custom functionality.
- In Java, this is where the "anonymous inner class" comes into play.
- To find out when the UI element (a View) gets clicked, we can call
setOnClickListener(), providing animplementationof anOnClickListener interface. - Rather than create a standalone class, though, we use anonymous inner class syntax to:
- Create a class.
- And a single instance of that class.
void clickyClickyClicky(View view) {
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO something useful.
}
});
}
- The Kotlin equivalent of this syntax is the "object expression".
Basic Declaration
- The Kotlin equivalent of the View and OnClickListener from above might look like this.
- Technically, in Android,
OnClickListeneris anested interfaceinside of View.
interface OnClickListener {
fun onClick(v: View)
}
class View {
fun setOnClickListener(listener: OnClickListener) {
// TODO something with this.
}
}
- When we want to call
setOnClickListener(), we could create astandalone classthat implements the OnClickListener interface. - Or, we could use an
object expression instead.- The
object keywordindicates that we are creating a single object. - The
: onClickListenerindicates that this object will implement the onClickListener interface.
- The
fun clickyClickClicky(view: View) {
view.setOnClickListener(object: OnClickListener {
override fun onClick(v: View) {
// TODO something useful.
}
})
}