2017-10-14 45 views
3

我是Kotlin的新手,並且正在解決返回不可變內部可變列表版本的問題。Kotlin:暴露API中的不可變列表

我回顧了下面的'Kotlin: Modifying (immutable) List through cast, is it legitimate?',並且明白不可變列表實際上只是只讀的視圖,不會公開修改方法。

我想有這暴露了一個「不變」列表中的一個類,並仍希望利用Kotlins自動干將(無需提供所有的樣板用於獲取列表或列表的成員)

在下面的一個壞主意(還是會引起可能在將來的版本中被阻塞的問題)

class Foo { 
    val names: List<String> = LinkedList; 

    fun addName(name: String) { 
    (names as LinkedList).add(name) 
    } 
} 

我期待允許(例如):

val foo = Foo; 
    println(foo.names.size) 

但是仍然阻止調用者修改類的內部(至少儘可能)。例如刪除元素或清除後備列表。

回答

4

以下工作:

class Foo { 
    private val _names: MutableList<String> = mutableListOf() 
    val names: List<String> 
     get() = _names.toList() 

    fun addName(name: String) { 
     _names.add(name) 
    } 
} 

的toList意味着,如果他們將它轉換爲一個MutableList<String>並嘗試添加到它,他們會得到一個UnsupportedOperationException,該_names字段保存真實的數據和外部訪問通過名稱屬性完成

+1

感謝jrtapsell, 是的,我知道我能保持這樣的第二個變量,以及...但不知道,如果需要額外的混亂.. 我認爲它是這樣工作的: 'VAL名:列表 = _names' – JWT

+0

...雖然這可能不會阻止轉換 – JWT

+0

names屬性只是用作_names的不可變視圖,但如果可以減少雜波將會很好 – jrtapsell

0

將可變列表定義爲具有下劃線(Kotlin中的一種「字段」)的私有屬性,並通過另一個公共只讀屬性公開它。

如果「場」是隻讀的,這是不行的(由@JWT建議)的伎倆 :

class Foo { 
    private val _names: MutableList<String> = mutableListOf() 
    val names: List<String> = _names 

    fun addName(name: String) { 
     _names.add(name) 
    } 
} 

如果「場」可能會被重新分配,則需要定義的getter作爲功能(注var _names):

class Foo2 { 
    private var _names: MutableList<String> = mutableListOf() 
    val names: List<String> 
     get() = _names 

    fun addName(name: String) { 
     _names.add(name) 
    } 

    fun reset() { 
     _names = mutableListOf() 
    } 
} 

測試可here