Design Converter
Education
Last updated on May 9, 2024
•12 mins read
Last updated on Apr 26, 2024
•12 mins read
Before we delve into the intricacies of Kotlin classes, it's paramount to lay a solid foundation. In Kotlin, classes are templates used to create objects; they define properties and behaviors that every object of that type will need. We use the class keyword to declare a class, followed by the class name. The implementation of the class is enclosed in curly braces.
1class Person { /*...*/ }
The class declaration consists of three major parts: the class name, the class header, and the class body. It's important to note that the class header is used to specify type parameters, and primary constructor parameters among other elements. Often, classes in Kotlin come with a body, which is surrounded by curly braces. However, it's not unusual to find an 'Empty' class without a body, hence no need for the curly braces.
1class Empty
Kotlin classes add a versatile and powerful tool to your programming arsenal, enabling you to model real-world entities, thus making your code more organized and reusable.
Kotlin is an object-oriented programming (OOP) language at its heart. The class concept, integral to OOP paradigms, is a centerpiece in Kotlin as well. Classes bring to the table capabilities to encapsulate data and functions that manipulate that data into a single unit, making this unit (object) a real-world entity.
While comparisons with Java classes are inevitable, Kotlin classes stand out for their concise syntax and explicit nature. For example, where Java necessitates that you write a lot of boilerplate code to achieve basic things like overloading constructors or generating getter and setter methods for class properties, Kotlin takes a different route. Kotlin's approach is focused on the concepts of classes and objects in a much cleaner and more efficient manner, making your work as a developer easier and your code more readable.
In essence, Kotlin addresses many problems faced by Java developers in dealing with classes, ranging from Null Pointer Exceptions to the verbosity of code, promoting a pragmatic and safer style of programming. But, of course, the list of Kotlin's offerings doesn't end here; there's more to this exciting world of Kotlin classes, which is what we'll plunge into next.
A Kotlin class has one primary constructor and possibly multiple secondary constructors to initialize an instance. The primary constructor in Kotlin forms part of the class header, following immediately after the class name and the optional type parameters.
1class Person constructor(firstName: String) { /*...*/ }
Here, the Person class has a primary constructor that takes a single parameter, firstName, of type String. You'll notice the precede constructor keyword before the parentheses enclosing the constructor parameters. If the primary constructor does not have any annotations or visibility modifiers, the constructor keyword can be disregarded.
1class Person(firstName: String) { /*...*/ }
In case we need to run code during object creation and initialization, we use initializer blocks with the init keyword inside the class body. The primary constructor is in charge of initializing the class instance and its properties in the class header.
1class InitOrderDemo(name: String) { 2 val firstProperty = "First property: $name".also(::println) 3 4 init { 5 println("First initializer block that prints $name") 6 } 7 8 val secondProperty = "Second property: ${name.length}".also(::println) 9 10 init { 11 println("Second initializer block that prints ${name.length}") 12 } 13}
Here, InitOrderDemo class accepts a name parameter in its primary constructor, which is then used to initialize properties and initializer blocks. Kotlin executes these initializer blocks in the order they appear in the class body. Primary constructor parameters can be used in the initializer blocks and can also be used in property initializers declared in the class body.
In Kotlin, the class header delivers a significant share of the preliminary details about a class. The header comprises annotations, visibility modifiers, type parameters, class name, and constructor declaration (both primary and secondary constructors).
A class can have one or more secondary constructors, where each constructor is prefixed by constructor keyword. If a class has a primary constructor, all secondary constructors must delegate to it directly or indirectly via another secondary constructor.
1class Person(val name: String) { 2 val children: MutableList<Person> = mutableListOf() 3 constructor(name: String, parent: Person) : this(name) { 4 parent.children.add(this) 5 } 6}
This Person class has a primary constructor and a secondary constructor. The secondary constructor accepts two parameters - name (a String) and parent (an instance of Person). This constructor initializes a new Person instance and then adds the new instance to the parent's list of children. The keyword this before the constructor parameters is used for the delegation to the primary constructor.
Having discussed Kotlin classes so far, let’s delve deeper and contrast two of Kotlin’s pivotal features - Kotlin object and class. Both serve distinct purposes and should be used appropriately.
A Kotlin class, as we’ve addressed, is a blueprint used to create objects with possible multiple instances. From the class, we create objects and then use these objects to call methods and properties. Classes contain constructors, initializer blocks, functions, properties, and nested and inner classes associated with them.
Furthermore, Kotlin classes allow for the creation of multiple class instances, each with its own unique state, which is particularly beneficial when using libraries like Jackson or JPA that create class instances through parameterless constructors, making it easier to work with these libraries. class Person(val firstName: String, val lastName: String, var age: Int) On the other hand, a Kotlin object is used to create a singleton, i.e., an object that cannot have multiple instances. The object keyword is used to create an object.
1object MySingleton { 2 fun doSomething() { 3 //... 4 } 5}
In the instance above, MySingleton is an object, not a class, which means you can’t create instances using the MySingleton declaration. You can directly call the member function, doSomething(), on MySingleton. MySingleton.doSomething() So the main difference boils down to the fact that while Kotlin classes are used when we want multiple instances with similar properties and behavior, Kotlin objects are used when we want a single instance.
In Kotlin, the sealed keyword is used to represent restricted class hierarchies. When a class is declared as sealed, it means that you can't create instances of this class in the same way you would a normal class; a Kotlin sealed class can only have subclasses as instances.
A sealed class is abstract by itself but can have multiple subclasses which could have multiple instances. Use cases for sealed classes primarily lie in state management, for example, to present the different states of a UI in an Android application.
1sealed class UiState { 2 object Success : UiState() 3 object Error : UiState() 4}
This prevents a hierarchy that is used when representing restricted states from becoming too large and not well-defined. This aids in writing robust, error-proof code.
Introduced in Kotlin 1.5.0, Kotlin value class were enable wrapping of a type without introducing the runtime overhead associated with classes while providing stronger type safety. A value class is defined as a Kotlin class with value modifier and has a single property defined in its primary constructor.
1@JvmInline 2value class Password(val s: String)
Here Password is a value class having a single String property s. Value classes can only have properties in the primary constructor, no additional properties or initializer blocks are allowed. Their purpose is to be a strong type check, ensuring runtime safety by avoiding bugs related to type mismatch.
A Kotlin abstract class is a class that cannot be instantiated (you cannot create objects of an abstract class). It is typically used as a base class for other classes that extend it. Abstract classes are designed to be inherited by subclasses, providing a template for functionality that must be created in derived classes.
To declare an abstract class in Kotlin, we use the abstract keyword:
1abstract class Polygon { 2 abstract fun draw() 3}
The Polygon abstract class has a single abstract method, draw(). Abstract methods do not have a body and hence, they need to be overridden in the subclass unless the subclass itself is abstract:
1class Rectangle : Polygon() { 2 override fun draw() { 3 // draw the rectangle 4 } 5}
Here Rectangle class extends the Polygon abstract class and provides its implementation for the draw() function. Abstract classes provide excellent flexibility and help reduce duplicate code, allowing you to define common functionalities in the base (abstract) class and unique features in subclasses that extend the abstract class.
Inheritance is one of the core principles of OOP which allows the creation of a new class using the properties and methods of an existing class (parent or base class). The new class that is created is referred to as the child class or derived class. When a class inherits from another, the latter is known as the parent class.
In Kotlin, to make a class inheritable, you must mark it with the open keyword. A class that doesn’t have the open keyword is final by default, and other classes cannot inherit from it. Furthermore, objects created from the same class in Kotlin each have their unique state, emphasizing the individuality of instances even when they originate from the same class.
1open class BaseClass { 2 //... 3} 4 5class DerivedClass : BaseClass() { 6 //... 7}
In the example above, the BaseClass is marked with the open modifier, and then DerivedClass extends BaseClass using the : symbol. Now DerivedClass has access to all the public and protected members of BaseClass.
Enums or Enumerations in Kotlin represent a type that can have a finite set of possible values (named constants). The enum keyword is used to declare an enumeration:
1enum class Direction { 2 NORTH, SOUTH, EAST, WEST 3}
Each enum constant is an instance of the enum class and they are separated by commas. You can initialize properties within enum constants, just like in a regular class, allowing your enums to be more versatile.
In Kotlin, the object keyword is used to create a singleton class. A singleton class means you can't create multiple instances or objects of that class. Only one instance of that class is created, and the same instance is used everywhere in the project.
1object MySingleton { 2 val variableName = "I am a Singleton object" 3 fun helloWorld() = println(variableName) 4} 5 6fun main(){ 7 MySingleton.helloWorld() 8}
In this example, MySingleton is an object that has a property and a function. The helloWorld() function can be called directly using the object name, MySingleton.
Kotlin supports the creation of constants at a compile-time which is achieved by using the const keyword in the variable declaration:
1const val PI = 3.14
Constructors in Kotlin are special member functions that are used to initialize properties of a class. A class in Kotlin has one primary constructor and one or more secondary constructor(s). The primary constructor is defined in the class header, it can have zero or more parameters.
1class Person(val firstName: String, val lastName: String) // Primary Constructor
Secondary constructors are defined inside the class body using the constructor keyword. They are used when we need to include more logic or multiple ways to initialize our class.
1class Person { 2 var children: MutableList<Person> = mutableListOf<Person>() 3 4 constructor(name: String, parent: Person) { 5 children.add(Person()) 6 } 7}
Kotlin's constructor and constant management features bring in an enhanced level of control and simplicity over the way developers initialize and manage variables. This makes code much cleaner and easy to read, thus contributing to overall code quality.
In Kotlin, interfaces are similar to abstract classes, except they can’t contain any state. An interface is declared using the interface keyword. It can contain abstract methods (methods without a body) as well as methods with a body.
1interface MyInterface{ 2 fun doSomething() // abstract method 3 4 fun display(){ 5 println("Display function in interface") // method with a body 6 } 7}
Classes or objects can implement an interface using the : symbol, just like with inheritance:
1class MyClass : MyInterface { 2 override fun doSomething() { 3 // provide implementation for doSomething 4 } 5}
Here MyClass implements MyInterface and provides an implementation for the abstract method doSomething(). The override keyword is crucial in Kotlin for labeling methods and properties being redefined from the interface or superclass, and it plays a key role in resolving method signature conflicts when a class implements multiple interfaces.
In Java, the extends keyword is used for class inheritance . However, in Kotlin, the : (colon) is used instead. Also, in Kotlin, all classes are final by default; you need to mark a class with an open modifier to allow it to be inheritable:
1open class BaseClass{ 2 //... 3} 4class DerivedClass: BaseClass() { 5 //... 6}
In the above example, DerivedClass extends the BaseClass.
Understanding Kotlin classes and their usage is fundamental to developing applications using Kotlin. Kotlin provides a wide variety of classes with unique features like primary and secondary constructors, sealed, value, and abstract classes. The introduction of safety mechanisms in class and object usage makes Kotlin a modern, expressive, and safer language that's enjoyable to use. By taking the time to learn and understand these basic concepts, you're well on your way to mastering Kotlin.
Learning Kotlin can be an exciting journey. Here are some resources that you might find useful:
• Kotlin Official Documentation
Armed with these resources, the knowledge in this blog, and consistent practice, you can quickly become proficient at Kotlin. Happy Kotlin learning!
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.