Pisałem mały fragment kodu, w którym wewnętrznie przetwarzam moje dane w zmiennej mapie, która z kolei ma zmienne listy.Jak zmienić kolekcję z możliwością modyfikacji w niezmienny?
Chciałem udostępnić moje dane użytkownikowi API, ale aby uniknąć niebezpiecznej publikacji moich danych, chciałem udostępnić je w niezmiennych kolekcjach, nawet jeśli wewnętrznie są obsługiwane przez zmienne.
class School {
val roster: MutableMap<Int, MutableList<String>> = mutableMapOf<Int, MutableList<String>>()
fun add(name: String, grade: Int): Unit {
val students = roster.getOrPut(grade) { mutableListOf() }
if (!students.contains(name)) {
students.add(name)
}
}
fun sort(): Map<Int, List<String>> {
return db().mapValues { entry -> entry.value.sorted() }
.toSortedMap()
}
fun grade(grade: Int) = db().getOrElse(grade, { listOf() })
fun db(): Map<Int, List<String>> = roster //Uh oh!
}
udało mi się wystawiać tylko Map
i List
(które są niezmienne) w publicznych API mojej klasy, ale przypadki Jestem rzeczywiście eksponujące są nadal natury zmienny.
Co oznacza, że użytkownik API może po prostu rzucić moją zwróconą mapę jako ImmutableMap i uzyskać dostęp do cennych prywatnych danych wewnętrznych mojej klasy, która miała być chroniona przed tego rodzaju dostępem.
Nie mogłem znaleźć konstruktora kopii w metodach fabryki kolekcji mutableMapOf()
lub mutableListOf()
i zastanawiałem się, jaki jest najlepszy i najskuteczniejszy sposób przekształcenia zmieniającej się kolekcji w niezmienny.
Wszelkie porady lub rekomendacje?
Pełniejsza wersja tego została dodana do Kluttera blokującego wszystkie powiązane akcje, takie jak 'Iterator' otrzymany z listy,' subList' z listy, 'entrySet' z mapy i więcej. Zobacz: http://stackoverflow.com/a/38002121/3679676 –