Intereting Posts
Как настроить JVM 9 на Kotlin с Gradle? Как издеваться над статическими методами в Котлине? Использование условия для выбора свойства сортировки в Котлине Невозможно скомпилировать функцию расширения с параметром типа reified в Kotlin libgdx AssetManager preload ttf шрифт не работает Ошибка сборки после обновления до Android Studio 3.0 с помощью Kotlin Мне нужен способ динамически, progammaticaly изменить фон для ImageView в представлении Recycler Тест для Android в котлинском царстве Вопрос о намерениях в приложении для Android от java до kotlin Неожиданная разница типов между эквивалентным Java и кодом потока Kotlin Компилятор Kotlin всегда сохраняет имена параметров в байт-коде? Asynctask несколько последовательных запросов URL в Android Kotlin: безопасные лямбда (нет утечки памяти)? Плагин Anko не может работать в версии Androidstudio> 2.1 Зачем нужен код B для использования SQLiteDatabase. () В параметре ввода?

Невозможно вызвать функцию из блока init из-за свойства val

Я хотел бы инициализировать свойства моего класса. Поскольку я сильно использую функциональные элементы Kotlin, я бы хотел поставить эти инициализации на хорошо названные функции, чтобы повысить читаемость моего кода. Проблема в том, что я не могу назначить свойство val, если код не находится в блоке init, а в функции, которая вызывается из блока init.

Можно ли разделить инициализацию класса на разные функции, если свойства являются vals?

Вот код:

val socket: DatagramSocket = DatagramSocket() val data: ByteArray = "Cassiopeiae server discovery packet".toByteArray() val broadcastAddresses: List<InetAddress> init { socket.broadcast = true val interfaceAddresses = ArrayList<InterfaceAddress>() collectValidNetworkInterfaces(interfaceAddresses) collectBroadcastAddresses(interfaceAddresses) } private fun collectValidNetworkInterfaces(interfaceAddresses: ArrayList<InterfaceAddress>) { NetworkInterface.getNetworkInterfaces().toList() .filter { validInterface(it) } .forEach { nInterface -> nInterface.interfaceAddresses.toCollection(interfaceAddresses) } } private fun collectBroadcastAddresses(interfaceAddresses: ArrayList<InterfaceAddress>) { broadcastAddresses = interfaceAddresses .filter { address -> address.broadcast != null } .map { it.broadcast } } 

Конечно, это не компиляция, потому что функция collectBroadcastAddresses пытается переназначить broadcastAddresses val. Хотя я не хочу помещать код этой функции в блок init, потому что не очевидно, что делает код, и имя функции говорит об этом очень красиво.

Что я могу сделать в таких случаях? Я хочу, чтобы мой код был чистым, это самый важный момент!

Solutions Collecting From Web of "Невозможно вызвать функцию из блока init из-за свойства val"

Одним из способов решения проблемы является использование чистых функций для инициализации полей:

 class Operation { val socket = DatagramSocket().apply { broadcast = true } val data: ByteArray = "Cassiopeiae server discovery packet".toByteArray() val broadcastAddresses = collectBroadcastAddresses(collectValidNetworkInterfaces()) private fun collectValidNetworkInterfaces() = NetworkInterface.getNetworkInterfaces().toList() .filter { validInterface(it) } .flatMap { nInterface -> nInterface.interfaceAddresses } private fun validInterface(it: NetworkInterface?) = true private fun collectBroadcastAddresses(interfaceAddresses: List<InterfaceAddress>) { interfaceAddresses .filter { address -> address.broadcast != null } .map { it.broadcast } } } 

Обратите внимание, как инициализация поля socket использует apply расширения.

Я часто считаю полезным извлекать подпрограммы обработки коллекций в методы расширения:

 class Operation { val socket = DatagramSocket().apply { broadcast = true } val data: ByteArray = "Cassiopeiae server discovery packet".toByteArray() val broadcastAddresses = NetworkInterface.getNetworkInterfaces() .collectValidNetworkInterfaces { validInterface(it) } .collectBroadcastAddresses() private fun validInterface(it: NetworkInterface?) = true } fun Iterable<InterfaceAddress>.collectBroadcastAddresses(): List<InetAddress> = filter { address -> address.broadcast != null }.map { it.broadcast } fun Enumeration<NetworkInterface>.collectValidNetworkInterfaces(isValid: (NetworkInterface) -> Boolean = { true }) = toList() .filter { isValid(it) } .flatMap { nInterface -> nInterface.interfaceAddresses }