由于val属性,无法从init块中调用函数

我想初始化我的类的属性。 因为我大量使用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块中,因为代码在做什么并不明显,而且函数的名字告诉它非常好。

在这种情况下我能做些什么? 我想保持我的代码清洁,这是最重要的一点!

解决这个问题的一种方法是使用纯函数来初始化字段:

 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 }