What is Inline(Value) Class in Kotlin

Oğuzhan Aslan
6 min readDec 30, 2022
Photo by Max Duzij on Unsplash

In programming, it is often necessary to represent values and data in a way that is convenient and efficient to work with. Kotlin provides several tools and techniques for representing values and data in your code. Just as traditional languages do, Kotlin has normal classes to represent a value. but it also provides even more advanced ways. These include value classes, data classes, Type-aliases.

Choosing the right approach for representing values and data in your Kotlin code will depend on your specific needs and the context in which you are using the values or data. In this article, we will talk about the value classes and the differences between other approaches.

A value class is a class in Kotlin that is designed to represent a single simple value, such as a Intor a String . This is because value classes are intended to represent simple values, and adding additional complexity would make them less efficient and less useful.

@JvmInline
value class Degree(val value: Double) {

fun toRadians(): Double = Math.toRadians(value)
fun toRotations(): Double = value / 360.0
fun sin(): Double = Math.sin(toRadians())
fun cos(): Double = Math.cos(toRadians())
fun tan(): Double = Math.tan(toRadians())
fun cot(): Double = 1.0 / tan()
fun sec(): Double = 1.0 / cos()
fun csc(): Double = 1.0 / sin()
}

The following traits apply to value classes:

  • They have a single property, which is the value they represent.
  • They are defined using the value keyword in the class definition.
  • They cannot have any custom initialization logic or any additional properties or functions beyond the value they represent.
  • They cannot be subclassed or extended.

Value classes are annotated with the @JvmInline annotation, which tells the Kotlin compiler to inline the class into its calling code. This means that the code for the value class is effectively copied into the calling code, eliminating the overhead of creating an object for the value class and making function calls on it. This can potentially improve performance by reducing the overhead of creating and using objects for simple values. However, inlining a value class can also increase the size of the generated code, as the code for the value class is copied into every place it is used. This can negatively impact performance if the value class is used in many places, as it can increase the overall size of the code and make it more difficult for the Just-In-Time (JIT) compiler to optimize the code.

Here is a valid value class :

but because of the points stated above such a code like this is not valid :

When you use a value class, you can create a new object on top of the value so that it can have more attributes and functions defined on it. This can be helpful if you want to combine numerous related values or if you want to provide the value multiple functionalities. In addition, the value type can be any class type, you are not limited using only primitives, but generally simple value types are prefered.

Recall that the value classes are different than type-aliases in Kotlin. A type-alias can mask a value type and may even make it even more readable, but remember that any actual type can be used in place of its type-alias. For instance:

If you give any other integer here instead of Degree , the compiler will not complain here. In such cases, type-aliases may be problematic and be risky to use. The semantic type-safety here does not exist in value classes since the value classes are, in the end, just classes and two different types are not the same. Even more, even if you try to use another value whose type same as the value classes value type, the compiler would not allow you to do so.

Cannot we just use Kotlin extension functions ?

Well yes
Well yes but no

The main difference between these two approaches is how the additional functionality is implemented and accessed.

If you are willing to just add one additional function to a given type, extension functions, probably, are choice. Extension functions allow you to add a single function to the given class without creating a new object. However, when you exceed this limit, using value classes seems to be a more reasonable to combine multiple functions together. Thus, they provide a better and more simple interface.

Ultimately, the choice between using a value class and an extension function will depend on your specific needs and the context in which you are using the value. Both approaches have their own pros and cons, and the right choice will depend on the specific requirements of your project.

On the other hand, I also stated that you can create a new object on top of the value with value classes.

What about using data classes ?

Data classes also contains value and can include its own functionalities. Also, they automatically generate a set of standard functions, including equals, hashCode, and toString, based on their properties which is not the case in value classes.

The main difference is that it can have multiple properties and have a custom initialization logic, meaning that you can manipulate the data that is passed to the data class in the init block. This is not the case in value classes. They cannot have any custom initialization logic. They are also not allowed to have any secondary constructors.

Furthermore, even if you use a single property in the data class you can still declare it varand change it in runtime. You would not be able to compile your code if you try to declare the value of the value class as var, which also means that the value of a value class is just a read-only property.

@JvmInline
value class Foo(var someValue: Int) { // invalid
fun doSomething() = println("do work do $someValue")
}

data class Bar(var someValue: Int) // valid

Additionally, Data classes can have multiple properties and custom initialization logic, whereas value classes cannot.

@JvmInline
value class Foo(val someValue: Int, val other : Int) { // invalid
fun doSomething() = println("do work do $someValue")
}

data class Bar(var someValue: Int, val other: Int) // valid

Also, value classes in Kotlin can potentially be more performant than data classes, because they are annotated with the @JvmInline annotation, which tells the Kotlin compiler to inline the class into its calling code. While,data classes is expensive. Instances of data classes are written to the heap, which takes more time and memory.

But this does not make the data classes a bad choice in every case. Data classes are still very useful for many cases, but when you have a single simple value and want to build an interface on top of it while still maintaining type safety, I believe that the value classes are more preferable.

We can list these value representations as:

  • Value classes are a way to represent simple values, such as numbers or strings, in a lightweight and efficient manner
  • Extension functions allow you to add additional functionality to existing classes without modifying the classes themselves.
  • Data classes are a way to represent more complex data structures, and provide a set of standard functions for working with the data.
  • Type aliases allow you to give a different name to an existing type, which can be useful for making your code more readable or for creating a more specific type to represent a value or data.

Overall, value classes are a useful tool for representing simple values in Kotlin, and can be particularly useful in contexts where performance is important and the overhead of creating and using objects for simple values needs to be minimized. If you are building a project in Kotlin and need to represent simple values efficiently, consider using value classes to improve the performance of your code. Understanding how value classes work and how to use them effectively can help you write efficient and effective Kotlin code.

Love you all.

Stay tuned for upcoming blogs.

Take care.

Linkedin

--

--