There is a KEEP proposal discussing this:
Is it to late for Kotlin to add an equivalent of C++ const keyword ?
class MyClass {
const fun bar() { ...} // 'const' mean bar doesn't change state of this
fun baz() { ... } //
}
class Demo {
private val _theThing = MyClass()
get theThing: const MyClass
}
fun main() {
Demo().theThing.bar() // legal
Demo().theThing.baz() // not legal => getter implie const object, baz function not declared const
}
The suggested variant
val items = mutableListOf<Item>() exposes List<Item>
looks really nice! It is readable, concise and self explanatory.
Yes, it’s fine for List (it’s already think in that way); but for custom class/interface, you have to create one readonly class/interface, and read/write class/interface that extends the first, with example i gave, you should code :
interface MyImmutable {
fun bar()
}
class MyClass : MyImmutable {
... overide method ...
fun baz() { ...}
}
it’s less convenient as const
keyword.
Is it to late for Kotlin to add an equivalent of C++ const keyword ?
JVM doesn’t have support of this. Moreover even final
field (e.g. val
in Kotlin terms) can be changed via reflection. Therefore there aren’t any performance benefits from this.
What do you try to achieve?
As far as I remember const in C++ is just a compile time type constraint, similar to non-null in Kotlin. Hence the jvm does not need to support it. It achieves for immutability typeness what nullabilty achieves in Kotlin.
The goal is not to gain about performance, but about expressivity and like fatjoe79 said, it’s a compile time constraint.
For example, on List class, instead of having mutable & immutable interface, we could have only one, with function that are readonly annotated as const
Then, a function that take a List as arguments with a const annotation could only call const function.
interface List<T> {
const fun get(i : Int) : T?
fun add(t : T)
}
fun read(const text : List<String>) {
text.get(0) // OK
text.add("new line") // not allowed, text is const
}
This topic starts being old but if someone is intereseted I have this solution :
class ListAccess<T>(private val list : List<T>) : List<T> by list
class MyClass {
private val _list : ArrayList<Int> = arrayListOf()
val list : ListAccess<Int> = ListAccess(_list)
}
Using List<Int>
where you have ListAccess<Int>
achieves the same.
The main difference is that ListAccess cannot be casted into a mutable list.
Purpose of this topic is not limited to List but to every mutable class.
For this, at least 2 strategy :
- for each mutable class, Build an interface for all read method; then, on function parameter, you have choice between class or interface. This is what is done on List.
- Add a “const” keyword that apply on function parameter.
First solution :
interface Read {
fun getValue() : String
}
class FullBean(var x : String) : Read {
override fun getValue(): String {
return x + "dd"
}
}
fun myFunc(r : Read) {
}
Second solution, with const keyword :
class Bean(var x : String) {
const fun getValue(): String {
return x + "dd"
}
}
fun myFunc(b1: const Bean, b2 : Bean, all : MutableList<const Bean>) : const Bean {
b2.x = b1.getValue()
all.add(b2)
return b2
}
Second solution is more straightforward.