Делегирование класса

Рейтинг: 1Ответов: 2Опубликовано: 28.05.2023

Я хочу иметь класс-обёртку, которая делегирует все свои public члены указанному объекту из этого класса. Для этого я использую ключевое слово by. Но этот код имеет несколько минусов:

  1. объект data приходится делать изменяемым, хотя он устанавливается всего один раз при инициализации.
  2. data не должен устанавливаться пользователем, но при этом его обязательно надо указать в первичном конструкторе.
class Cache(
    private val file: File,
    private var data: MutableMap<String, String> = mutableMapOf()
) : MutableMap<String, String> by data {

    init {
        data = Json.decodeFromStream(file.inputStream())
    }

    fun save() {
        Json.encodeToStream(data, file.outputStream())
    }
}

Какой самый логичный выход из этой ситуации?
Требуется, чтобы класс Cache обязательно реализовывал интерфейс MutableMap<String, String>.

Ответы

▲ 1Принят

Если параметр data в конструкторе не нужен, то его можно оттуда убрать. При этом добавить начальные данные из файла можно будет с помощью метода putAll():

class Cache(
    private val file: File
) : MutableMap<String, String> by mutableMapOf() {

    init {
        putAll(Json.decode(file))
    }

    ...

}
▲ 1

Спасибо! Хочу оставить также своё решение:

class Cache(
    private val file: File
) : MutableMap<String, String> by loadFromJsonFile(file) {

    private companion object {
        fun loadFromJsonFile(file: File): MutableMap<String, String> {
            return Json.decodeFromStream(file.inputStream())
        }
    }

    fun save() {
        Json.encodeToStream(this, file.outputStream())
    }
}

Здесь используется private companion object для инкапсуляции и начальной инициализации данных. Решение может быть полезно тем, кому необходима неизменяемая Map.