当前位置: 首页 > 知识库问答 >
问题:

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

俞涵涤
2023-03-14

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

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

代码如下:

    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块,因为代码的作用并不明显,函数名很好地说明了这一点。

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

共有1个答案

诸葛康胜
2023-03-14

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

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 }
    }
}

请注意套接字字段初始化如何使用扩展名。

我经常发现将集合操作例程提取到扩展方法中很有用:

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 }
 类似资料:
  • 我是Firebase函数的新手,在官方文档中看到了一些变化,但是当我在做一个通知系统时,当我试图获取我的令牌id时,它抛出了这个错误。 我的代码 错误 无法在导出处读取未定义的属性“val”.js user_code。(/user_code/node_modules/火库函数/库/云函数.js:112:27) 在下一个 (本机) 在 /user_code/node_modules/火基函数/库/云

  • 以下作品 而这不是(未解决的引用:tabCount) 我是Kotlin的新手,只是不明白为什么不能在类本身中使用val属性。有人能解释一下吗?谢谢

  • 问题内容: 考虑以下示例。 如果我尝试更改类实例的变量,则编译成功。 但是,如果我尝试更改method 的返回值,则编译会发出尖叫 有人可以解释一下。 问题答案: 这是编译器告诉您的修改无用的方式。 这是发生了什么:当你打电话,一个 副本 的回传给你。该副本是 临时的 。您可以检查其字段,或将其分配给变量(在这种情况下,您将能够重新访问您的修改)。如果编译器允许您对该临时结构进行修改,则将无法访问

  • 我是kubernetes的新手,正在尝试配置kubernetes主节点,我已经安装了kubeadm、kubectl和kubelet,如下所示 https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/ 但是当我尝试通过键入 kubeadm 时,它会给我以下错误

  • 更新:我发布了两个更简洁的代码片段,说明了混乱的根源: https://gist.github.com/mttkay/9fbb0ddf72f471465afc https://gist.github.com/mttkay/5dc9bde1006b70e1e8ba

  • 问题内容: 使用注释和声明与 Spring XML配置中相同的方法之间有什么区别吗? 问题答案: 实际上,我不认为没有任何区别,但是它们的工作方式存在优先级。@PostConstruct,init-method是BeanPostProcessors。 是JSR-250注释,而是具有初始化方法的方法。 如果有方法,将在调用初始化方法之前先调用此方法。 如果你的bean实现的和覆盖,首先被调用,然后t