Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type of object returned by listOf Kotlin

Tags:

kotlin

As Kotlin documentation says listOf<T> has three implementations: for no arguments, one argument and varargs. Each function should return immutable List<T>.

val emptyList = listOf<String>()
val oneArgList = listOf("asd")
val varargsList = listOf("asd", "asd")

if (emptyList is MutableList) println("emptyList is mutable")
if (oneArgList is MutableList) println("oneArgList is mutable")
if (varargsList is MutableList) println("varargList is mutable")

Execution of code above results in

oneArgList is mutable
varargList is mutable

Why it works that way? Is this desired behaviour?

like image 663
1212q Avatar asked Feb 24 '20 18:02

1212q


2 Answers

Why it works that way?

If you check out the source code, you will find it actually creates a Java ArrayList. This leverages the JDK instead of having to implement an ArrayList in Kotlin. Note that your cast to MutableList is a bad coding practice even if it is successful since the listOf() function already specifies it is a List and not a MutableList.

emptyList() (or listOf()) on the other hand uses an EmptyList singleton implemented in Kotlin that is truly immutable.

Is this desired behaviour?

Actually no. However it does the trick presenting an immutable interface instead. It doesn't really matter how exactly the backing data structure is implemented as long as it conforms to the interface contract. You as a programmer should also stick to the contract when using it.

like image 160
m0skit0 Avatar answered Oct 11 '22 03:10

m0skit0


You say "each one should return immutable lists", but if you look at the documentation for the three functions, the first one says it returns an immutable List, and the next two say they return a read-only List. A read-only List is not necessarily immutable.

The List interface does not guarantee immutability. It only describes itself as providing solely read-only methods.

In actual practice, haphazardly doing is checks is a big time code smell. There are some narrow use cases that kind of make sense. Like Google's recommended way to create a DialogFragment and communicate back to the Activity, but stuff like this is (IMO) a hack to get around regrettable decisions from the original design of Activities and Fragments. In the case of this example, you would control the definition of your interface, and all implementations of it, so its a little harder for things to go wrong.

like image 34
Tenfour04 Avatar answered Oct 11 '22 03:10

Tenfour04