我想初始化我班级的属性.因为我大量使用Kotlin的功能元素,所以我想将这些初始化放在命名良好的函数中,以提高代码的可读性.问题是我不能分配val属性,如果代码不在init块中,而是在从init块调用的函数中.
如果属性是val,是否可以将类的初始化拆分为不同的函数?
这是代码:
val socket: DatagramSocket = DatagramSocket() val data: ByteArray = "Cassiopeiae server discovery packet".toByteArray() val broadcastAddresses: Listinit { socket.broadcast = true val interfaceAddresses = ArrayList () collectValidNetworkInterfaces(interfaceAddresses) collectBroadcastAddresses(interfaceAddresses) } private fun collectValidNetworkInterfaces(interfaceAddresses: ArrayList ) { NetworkInterface.getNetworkInterfaces().toList() .filter { validInterface(it) } .forEach { nInterface -> nInterface.interfaceAddresses.toCollection(interfaceAddresses) } } private fun collectBroadcastAddresses(interfaceAddresses: ArrayList ) { 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) { 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.collectBroadcastAddresses(): List = filter { address -> address.broadcast != null }.map { it.broadcast } fun Enumeration .collectValidNetworkInterfaces(isValid: (NetworkInterface) -> Boolean = { true }) = toList() .filter { isValid(it) } .flatMap { nInterface -> nInterface.interfaceAddresses }