Object expressions and declarations
Sometimes you need to create an object that is a slight modification of some class, without explicitly declaring a new subclass for it. Kotlin can handle this with object expressions and object declarations.
Object expressions create objects of anonymous classes, that is, classes that aren't explicitly declared with the
class declaration. Such classes are useful for one-time use. You can define them from scratch, inherit from existing classes, or implement interfaces. Instances of anonymous classes are also called anonymous objects because they are defined by an expression, not a name.
Creating anonymous objects from scratch
Object expressions start with the
If you just need an object that doesn't have any nontrivial supertypes, write its members in curly braces after
Inheriting anonymous objects from supertypes
To create an object of an anonymous class that inherits from some type (or types), specify this type after
object and a colon (
:). Then implement or override the members of this class as if you were inheriting from it:
If a supertype has a constructor, pass appropriate constructor parameters to it. Multiple supertypes can be specified as a comma-delimited list after the colon:
Using anonymous objects as return and value types
If this function or property is public or private inline, its actual type is:
Anyif the anonymous object doesn't have a declared supertype
The declared supertype of the anonymous object, if there is exactly one such type
The explicitly declared type if there is more than one declared supertype
In all these cases, members added in the anonymous object are not accessible. Overridden members are accessible if they are declared in the actual type of the function or property:
Accessing variables from anonymous objects
The code in object expressions can access variables from the enclosing scope:
The Singleton pattern can be useful in several cases, and Kotlin makes it easy to declare singletons:
This is called an object declaration, and it always has a name following the
object keyword. Just like a variable declaration, an object declaration is not an expression, and it cannot be used on the right-hand side of an assignment statement.
The initialization of an object declaration is thread-safe and done on first access.
To refer to the object, use its name directly:
Such objects can have supertypes:
When printing a plain
object declaration in Kotlin, you'll notice that its string representation contains both its name and the hash of the object:
Just like data classes, you can mark your
object declaration with the
data modifier to get a nicely formatted string representation without having to manually provide an implementation for its
Sealed class hierarchies are a particularly good fit for
data object declarations, since they allow you to maintain symmetry with any data classes you might have defined alongside the object:
An object declaration inside a class can be marked with the
Members of the companion object can be called simply by using the class name as the qualifier:
The name of the companion object can be omitted, in which case the name
Companion will be used:
Class members can access the private members of the corresponding companion object.
The name of a class used by itself (not as a qualifier to another name) acts as a reference to the companion object of the class (whether named or not):
Note that even though the members of companion objects look like static members in other languages, at runtime those are still instance members of real objects, and can, for example, implement interfaces:
However, on the JVM you can have members of companion objects generated as real static methods and fields if you use the
@JvmStatic annotation. See the Java interoperability section for more detail.
Semantic difference between object expressions and declarations
There is one important semantic difference between object expressions and object declarations:
Object expressions are executed (and initialized) immediately, where they are used.
Object declarations are initialized lazily, when accessed for the first time.
A companion object is initialized when the corresponding class is loaded (resolved) that matches the semantics of a Java static initializer.