Classes
Like other object-oriented languages, Kotlin uses classes to encapsulate data (properties) and behavior (functions) for reusable, structured code.
Classes are blueprints or templates for objects, which you create via constructors. When you create an instance of a class, you are creating a concrete object based on that blueprint.
Kotlin offers concise syntax for declaring classes. To declare a class, use the class
keyword followed by the class name:
The class declaration consists of:
Class header, including but not limited to:
class
keywordClass name
Type parameters (if any)
Primary constructor (optional)
Class body (optional), surrounded by curly braces
{}
, and including class members such as:
You can keep both the class header and body to a bare minimum. If the class doesn't have a body, you can omit the curly braces {}
:
Here's an example that declares a class with a header and body, then creates an instance from it:
Creating instances
An instance is created when you use the class as a blueprint to build a real object to work with in your program.
To create an instance of a class, use the class name followed by parentheses ()
, similar to calling a function:
In Kotlin, you can create instances:
Without arguments (
Person()
): creates an instance using the default values, if they are declared in the class.With arguments (
Person(value)
): creates an instance by passing specific values.
You can assign the created instance to a mutable (var
) or read-only (val
) variable:
It's possible to create instances wherever you need them, inside the main()
function, within other functions, or inside another class. Additionally, you can create instances inside another function and call that function from main()
.
The following code declares a Person
class with a property for storing a name. It also demonstrates how to create an instance with both the default constructor's value and a specific value:
For information about creating instances of nested, inner, and anonymous inner classes, see the Nested classes section.
Constructors and initializer blocks
When you create a class instance, you call one of its constructors. A class in Kotlin can have a primary constructor and one or more secondary constructors.
The primary constructor is the main way to initialize a class. You declare it in the class header. A secondary constructor provides additional initialization logic. You declare it in the class body.
Both primary and secondary constructors are optional, but a class must have at least one constructor.
Primary constructor
The primary constructor sets up the initial state of an instance when it's created.
To declare a primary constructor, place it in the class header after the class name:
If the primary constructor doesn't have any annotations or visibility modifiers, you can omit the constructor
keyword:
The primary constructor can declare parameters as properties. Use the val
keyword before the argument name to declare a read-only property and the var
keyword for a mutable property:
These constructor parameter properties are stored as part of the instance and are accessible from outside the class.
It's also possible to declare primary constructor parameters that are not properties. These parameters don't have val
or var
in front of them, so they are not stored in the instance and are available only within the class body:
Properties declared in the primary constructor are accessible by member functions of the class:
You can also assign default values to properties in the primary constructor:
If no value is passed to the constructor during instance creation, properties use their default value:
You can use the primary constructor parameters to initialize additional class properties directly in the class body:
As with functions, you can use trailing commas in constructor declarations:
Initializer blocks
The primary constructor initializes the class and sets its properties. In most cases, you can handle this with simple code.
If you need to perform more complex operations during instance creation, place that logic in initializer blocks inside the class body. These blocks run when the primary constructor executes.
Declare initializer blocks with the init
keyword followed by curly braces {}
. Write within the curly braces any code that you want to run during initialization:
Add as many initializer blocks (init {}
) as you need. They run in the order in which they appear in the class body, along with property initializers:
You can use primary constructor parameters in initializer blocks. For example, in the code above, the first and second initializers use the name
and age
parameters from the primary constructor.
A common use case for init
blocks is data validation. For example, by calling the require
function:
Secondary constructors
In Kotlin, secondary constructors are additional constructors that a class can have beyond its primary constructor. Secondary constructors are useful when you need multiple ways to initialize a class or for Java interoperability.
To declare a secondary constructor, use the constructor
keyword inside the class body with the constructor parameters within parentheses ()
. Add the constructor logic within curly braces {}
:
In the code above, the secondary constructor delegates to the primary constructor via the this
keyword, passing name
and the age
value converted to an integer.
In Kotlin, secondary constructors must delegate to the primary constructor. This delegation ensures that all primary constructor initialization logic is executed before any secondary constructor logic runs.
Constructor delegation can be:
Direct, where the secondary constructor calls the primary constructor immediately.
Indirect, where one secondary constructor calls another, which in turn delegates to the primary constructor.
Here's an example demonstrating how direct and indirect delegation works:
In classes with initializer blocks (init {}
), the code within these blocks becomes part of the primary constructor. Given that secondary constructors delegate to the primary constructor first, all initializer blocks and property initializers run before the body of the secondary constructor. Even if the class has no primary constructor, the delegation still happens implicitly:
Classes without constructors
Classes that don't declare any constructors (primary or secondary) have an implicit primary constructor with no parameters:
The visibility of this implicit primary constructor is public, meaning it can be accessed from anywhere. If you don't want your class to have a public constructor, declare an empty primary constructor with non-default visibility:
Inheritance
Class inheritance in Kotlin allows you to create a new class (derived class) from an existing class (base class), inheriting its properties and functions while adding or modifying behavior.
For detailed information about inheritance hierarchies and how to use of the open
keyword, see the Inheritance section.
Abstract classes
In Kotlin, abstract classes are classes that can't be instantiated directly. They are designed to be inherited by other classes which define their actual behavior. This behavior is called an implementation.
An abstract class can declare abstract properties and functions, which must be implemented by subclasses.
Abstract classes can also have constructors. These constructors initialize class properties and enforce required parameters for subclasses. Declare an abstract class using the abstract
keyword:
An abstract class can have both abstract and non-abstract members (properties and functions). To declare a member as abstract, you must use the abstract
keyword explicitly.
You don't need to annotate abstract classes or functions with the open
keyword because they are implicitly inheritable by default. For more details about the open
keyword, see Inheritance.
Abstract members don't have an implementation in the abstract class. You define the implementation in a subclass or inheriting class with an override
function or property:
Companion objects
In Kotlin, each class can have a companion object. Companion objects are a type of object declaration that allows you to access its members using the class name without creating a class instance.
Suppose you need to write a function that can be called without creating an instance of a class, but it is still logically connected to the class (such as a factory function). In that case, you can declare it inside a companion object declaration within the class:
If you declare a companion object inside your class, you can access its members using only the class name as a qualifier.
For more information, see Companion objects.