# Objects
The
object
keyword defines something that looks roughly like a class. However, you can’t create instances of anobject
—there’s only one. This is sometimes called the Singleton pattern.
An object
is a way to combine functions and properties that logically belong together, but this combination either doesn’t require multiple instances, or you want to explicitly prevent multiple instances. You never create an instance of an object
—there’s only one and it’s available once the object
has been defined:
// Objects/ObjectKeyword.kt
package objects
import atomictest.eq
object JustOne {
val n = 2
fun f() = n * 10
fun g() = this.n * 20 // [1]
}
fun main() {
// val x = JustOne() // Error
JustOne.n eq 2
JustOne.f() eq 20
JustOne.g() eq 40
}
Here, you can’t say JustOne()
to create a new instance of a class JustOne
. That’s because the object
keyword defines the structure and creates the object at the same time. In addition, it places the elements inside the object
’s namespace. If you only want the object
to be visible within the current file, you can make it private
.
- [1] The
this
keyword refers to the single object instance.
You cannot provide a parameter list for an object
.
Naming conventions are slightly different when using object
. Typically, when we create an instance of a class, we lower-case the first letter of the instance name. When you create an object
, however, Kotlin defines the class and creates a single instance of that class. We capitalize the first letter of the object
name because it also represents a class.
An object
can inherit from a regular class or interface:
// Objects/ObjectInheritance.kt
package objects
import atomictest.eq
open class Paint(val color: String) {
open fun apply() = "Applying $color"
}
object Acrylic: Paint("Blue") {
override fun apply() =
"Acrylic, ${super.apply()}"
}
interface PaintPreparation {
fun prepare(): String
}
object Prepare: PaintPreparation {
override fun prepare() = "Scrape"
}
fun main() {
Prepare.prepare() eq "Scrape"
Paint("Green").apply() eq "Applying Green"
Acrylic.apply() eq "Acrylic, Applying Blue"
}
There’s only a single instance of an object
, so that instance is shared across all code that uses it. Here’s an object
in its own package
:
// Objects/GlobalSharing.kt
package objectsharing
object Shared {
var i: Int = 0
}
We can now use Shared
in a different package:
// Objects/Share1.kt
package objectshare1
import objectsharing.Shared
fun f() {
Shared.i += 5
}
And within a third package:
// Objects/Share2.kt
package objectshare2
import objectsharing.Shared
import objectshare1.f
import atomictest.eq
fun g() {
Shared.i += 7
}
fun main() {
f()
g()
Shared.i eq 12
}
You can see from the results that Shared
is the same object in all packages, which makes sense because object
creates a single instance. If you make Shared
private
, it’s not available in the other files.
object
s can’t be placed inside functions, but they can be nested inside other object
s or classes (as long as those classes are not themselves nested within other classes):
// Objects/ObjectNesting.kt
package objects
import atomictest.eq
object Outer {
object Nested {
val a = "Outer.Nested.a"
}
}
class HasObject {
object Nested {
val a = "HasObject.Nested.a"
}
}
fun main() {
Outer.Nested.a eq "Outer.Nested.a"
HasObject.Nested.a eq "HasObject.Nested.a"
}
There’s another way to put an object inside a class: a companion object
, which you’ll see in the [Companion Objects](javascript:void(0)) atom.
Exercises and solutions can be found at www.AtomicKotlin.com.