Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin, set var/val once to make it final, is that possible

Tags:

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?

like image 941
Elye Avatar asked Feb 19 '18 01:02

Elye


People also ask

Is Val final in Kotlin?

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!

Can Val be changed?

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.

How do I assign a Val in Kotlin?

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.


2 Answers

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;
like image 105
Makoto Avatar answered Sep 22 '22 12:09

Makoto


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.

like image 32
EmilioPelaez Avatar answered Sep 19 '22 12:09

EmilioPelaez