Matthew Layton
Matthew Layton

Reputation: 42229

Kotlin - An Elegant Way to Expose a Mutable List as an Immutable List

I have a class where I want to be able to modify a list internally, but externally I want the list to be immutable; for example...

class Foo {
    val items: List<String> get() = mutableItems
    private val mutableItems: MutableList<String> = mutableListOf()
}

Is there a nicer way to express this?

Upvotes: 6

Views: 2171

Answers (3)

Tenfour04
Tenfour04

Reputation: 93581

Edit: The feature originally described below has evolved into the explicit backing fields feature, which is currently prototyped in the K2 compiler. With explicit backing fields, the syntax would be:

val items: List<String>
    field = mutableListOf()

Original answer:

No, but they have something in the works that might appear in a future version of Kotlin. The suggested syntax would look something like this:

private val items: MutableList<String> = mutableListOf()
    public get(): List<String>

This was presented by the language design lead in a talk about possible future features of Kotlin.

To be a bit pedantic, you are exposing a read-only List, not an immutable one.

Upvotes: 8

dkarczmarski
dkarczmarski

Reputation: 11

A similar example can be found in the Kotlin documentation under "Backing properties" (https://kotlinlang.org/docs/properties.html#backing-properties).

They have a private variable _table type of Map<String, Int>? but it is exposed outside as Map<String, Int>.

private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
    get() {
        if (_table == null) {
            _table = HashMap() // Type parameters are inferred
        }
        return _table ?: throw AssertionError("Set to null by another thread")
    }

In your case you can do something like this:

class Foo {
    private val _items: MutableList<String> = mutableListOf()

    val items: List<String>
        get() = _items

    // ...
    fun addItem(item: String) = _items.add(item)
}

or

class Foo {
    private val _items: MutableList<String> = mutableListOf()

    val items: List<String> = _items

    // ...
    fun addItem(item: String) = _items.add(item)
}

.

Is it "An Elegant Way" to use a private property with underscore sign?

Upvotes: 0

Rasul
Rasul

Reputation: 792

You can do something like this:

private val items : MutableList<String> = mutableListOf()
fun items() : List<String> = items

When you want to access your items externally just use items() function. In internal usage work with list directly

Upvotes: -2

Related Questions