当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《由于val属性,无法从init块调用函数》经验,为你挑选了1个好方法。

我想初始化我班级的属性.因为我大量使用Kotlin的功能元素,所以我想将这些初始化放在命名良好的函数中,以提高代码的可读性.问题是我不能分配val属性,如果代码不在init块中,而是在从init块调用的函数中.

如果属性是val,是否可以将类的初始化拆分为不同的函数?

这是代码:

    val socket: DatagramSocket = DatagramSocket()
    val data: ByteArray = "Cassiopeiae server discovery packet".toByteArray()
    val broadcastAddresses: List

    init {
        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块中,因为代码在做什么并不明显,而且函数名称非常好.

在这种情况下我该怎么办?我想保持我的代码干净,这是最重要的一点!



1> miensol..:

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

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 }

推荐阅读
牛尾巴2010
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有