如何从父类构造参数创建Kotlin伴生对象变量?
问题:如何在伴生对象中存储带引用字符串的Gpio对象?
我正在开发一款应用,需要在内存中存储带有引用字符串的对象,因此考虑使用类似单例的伴生对象。但尝试将构造参数gpioName和pinGPIO传入伴生对象的Map时出现错误,代码示例如下:
class PulseSender(gpioName: String) { internal val logger = getLogger("PIN/PAD", "PAX-Device") private val peripheralManager = PeripheralManager.getInstance() private val pinGPIO: Gpio = peripheralManager.openGpio(gpioName) companion object{ val gpio : Map<String, Gpio> = mapOf(gpioName, pinGPIO) //这里两个参数都报错 } val staticGpio get() = gpio // ...其他代码 }
请问如何正确传递这些参数(gpioName为字符串,Gpio为对象),或是我应该更换实现方案?
解决方案
错误原因
伴生对象是类级别的静态成员,在类加载阶段就完成初始化,它无法访问任何实例级别的变量——gpioName是构造参数(属于每个实例),pinGPIO是实例属性,伴生对象根本看不到这些数据,所以会报错。
分场景解决
根据你的实际需求,有两种可行方案:
场景1:全局共享所有已打开的Gpio实例
如果要让所有PulseSender实例共用一份全局的Gpio映射,可将伴生对象的Map改为可变类型,在实例初始化时添加数据:
class PulseSender(gpioName: String) { internal val logger = getLogger("PIN/PAD", "PAX-Device") private val peripheralManager = PeripheralManager.getInstance() private val pinGPIO: Gpio = peripheralManager.openGpio(gpioName) companion object{ // 内部用可变Map,对外暴露不可变视图,避免外部修改 private val _gpio: MutableMap<String, Gpio> = mutableMapOf() val gpio: Map<String, Gpio> get() = _gpio } // 实例初始化时把当前Gpio加入全局映射 init { // 可按需处理重复key:比如直接覆盖,或者判断后跳过 companion._gpio[gpioName] = pinGPIO } val staticGpio get() = gpio // ...其他代码 }
注意:如果是多线程环境,要给Map的操作加锁,或者改用ConcurrentHashMap保证线程安全。
场景2:每个实例拥有自己的Gpio映射
如果只是每个PulseSender实例单独存储自己对应的Gpio,完全不需要伴生对象,直接定义为实例属性即可:
class PulseSender(gpioName: String) { internal val logger = getLogger("PIN/PAD", "PAX-Device") private val peripheralManager = PeripheralManager.getInstance() private val pinGPIO: Gpio = peripheralManager.openGpio(gpioName) // 每个实例独立的Map val gpio: Map<String, Gpio> = mapOf(gpioName to pinGPIO) val staticGpio get() = gpio // ...其他代码 }
方案选择建议
- 若要全局统一管理所有已打开的Gpio,选场景1的方案;
- 若只是每个实例自己存对应的映射,场景2的方案更简单直接,没必要用伴生对象。
内容的提问来源于stack exchange,提问作者Manuel Lucas
相关产品推荐
相关产品推荐

