In Kotlin, we have val
that is final and can't be change. e.g.
val something = "Something"
If a value that is is initialized later, we use lateinit var
.
lateinit var something: String
But this is var
instead of val
. I wanted to set something once (not in constructor), and have it as final. How could I achieve this?
Most Kotlin developers would agree that a val property is equivalent to a final property in Java. What if I tell you that this is not completely true and sometimes you might need a final val ? Opposite to Java, Kotlin properties are final by default unless they are explicitly marked as open!
Once a value is assigned to a variable with the val keyword, it cannot be altered or reassigned throughout the program. Val is similar to the final keyword in Java.
Kotlin uses two different keywords to declare variables: val and var . Use val for a variable whose value never changes. You can't reassign a value to a variable that was declared using val . Use var for a variable whose value can change.
Reading into the conventions of Kotlin, a late-initialized variable which is final is impossible.
Consider its use case:
Normally, properties declared as having a non-null type must be initialized in the constructor. However, fairly often this is not convenient. For example, properties can be initialized through dependency injection, or in the setup method of a unit test. In this case, you cannot supply a non-null initializer in the constructor, but you still want to avoid null checks when referencing the property inside the body of a class.
lateinit var
is providing relative sanity when dealing with a variable that may not have yet been initialized, such as the case with injected fields (like Spring and @Autowired
). Then, speaking strictly in the context of dependency injection, if you don't have a way to concretely instantiate the variable at compile time, then you cannot leave it as a final field.
From a Java to Kotlin world, having a late initialized variable come in as final would look as paradoxical as this from Spring:
@Autowired
private final Interface something;
What do you think the behavior should be when you attempt to set it again? Do you expect this to be enforced at compile time? Should it cause a crash at runtime or just do nothing?
If you expect it to happen at compile time, I'm pretty sure it's not possible for a compiler to catch something like that.
If you want some other behavior, you can make it a private variable with a public set method that does whatever you want if it's been already set.
Or you could encapsulate it in an instance of a custom class that does whatever behavior you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With