Kotlin 如何发送和接收列表中的一般类型对象

Kotlin 如何发送和接收列表中的一般类型对象,kotlin,Kotlin,我试图创建一个类,其中通过接口有两个重写函数。接口将是泛型的,我希望函数是简单的转换 然而,我已经能够做到这一点,当我创建这些对象的多个对象并将它们放入一个列表并单独访问它们时,应该将泛型类型作为输入的函数会给出错误:类型不匹配:推断的类型是任意的,但没有预期的 换言之: interface ConverterInterface<T>{ fun sender(value: T): ByteArray fun receiver(bytes: ByteArray): T

我试图创建一个类,其中通过接口有两个重写函数。接口将是泛型的,我希望函数是简单的转换

然而,我已经能够做到这一点,当我创建这些对象的多个对象并将它们放入一个列表并单独访问它们时,应该将泛型类型作为输入的函数会给出错误:
类型不匹配:推断的类型是任意的,但没有预期的

换言之:

interface ConverterInterface<T>{
    fun sender(value: T): ByteArray
    fun receiver(bytes: ByteArray): T
}
接口转换器接口{
乐趣发送者(值:T):ByteArray
趣味接收器(字节:ByteArray):T
}
这在首次实施时确实有效:

class TestClass {
    val objA = object: ConverterInterface<String>{
        override fun sender(value: String): ByteArray {
            //...
        }

        override fun receiver(bytes: ByteArray): String {
            //...
        }
    }
}
class测试类{
val objA=对象:转换器接口{
重写趣味发送器(值:字符串):ByteArray{
//...
}
覆盖有趣的接收器(字节:ByteArray):字符串{
//...
}
}
}
但是,我希望存储这些对象的列表,并在以后访问它们

fun test(){
    val testList: List<ConverterInterface<*>> = listOf(objA)

    // This works
    testList[0].receiver(byteArrayOf())

    // This does not
    testList[0].sender("")
    /* Out-projected type 'ConverterInterface<*>' prohibits the use of
    'public abstract fun sender(value: T): ByteArray defined in ConverterInterface */
}
fun测试(){
val testList:List=listOf(objA)
//这很有效
测试列表[0]。接收器(byteArrayOf())
//这是不可能的
测试列表[0]。发件人(“”)
/*外投影类型“转换器接口”禁止使用
'公共抽象趣味发送器(值:T):在ConverterInterface中定义的ByteArray*/
}
我必须对列表类型使用通配符
*
,因为如果我尝试使用
任何
我会得到一个类型推断失败的错误。要使其工作,我可以将类型设置为“输出任何”,但这不会修复任何问题,只会导致“接收器”功能工作


我觉得我想做的可能不可能。简单地说,我希望能够在不进行类型转换的情况下访问这些函数。

我不确定这是否是一个好的解决方案,但以下是我的想法。我创建了一个抽象类,该类实现了接口,但还包含一个用于发送方的预定义函数,该函数在内部强制转换为
T

interface ConverterInterface<T>{
    fun sender(value: T): ByteArray
    fun receiver(bytes: ByteArray): T
}

abstract class TestClass<T> : ConverterInterface<T>{
    fun realSender(value: Any): ByteArray{
        @Suppress("UNCHECKED_CAST")
        return sender(value as T)
    }
}

val testObj = object: TestClass<String>(){
    override fun sender(value: String): ByteArray {
        return byteArrayOf()
    }
    override fun receiver(bytes: ByteArray): String {
        return ""
    }

}

val testList: List<TestClass<*>> = listOf(testObj)

fun a(){
    testList[0].realSender("")
    testList[0].receiver(byteArrayOf())
}
接口转换器接口{
乐趣发送者(值:T):ByteArray
趣味接收器(字节:ByteArray):T
}
抽象类TestClass:转换器接口{
fun realSender(值:任意):ByteArray{
@抑制(“未选中的_CAST”)
返回发送方(值为T)
}
}
val testObj=对象:TestClass(){
重写趣味发送器(值:字符串):ByteArray{
返回byteArrayOf()
}
覆盖有趣的接收器(字节:ByteArray):字符串{
返回“”
}
}
val testList:List=listOf(testObj)
乐趣a(){
测试列表[0]。realSender(“”)
测试列表[0]。接收器(byteArrayOf())
}

我知道这个函数现在接受任何输入,这可能会导致异常,但到目前为止,这是我唯一能想到的解决方案。另外,至少在我的情况下,类的函数不应该接收泛型以外的任何内容,因此传入的不同类型的值将是一个例外。

我认为您必须在这里进行一些重新设计。编译器警告您代码中存在严重的类型安全问题,如果您没有正确修复它,它很可能会回来咬你

您有一个转换器的
列表
,但您无法说出每个转换器可以转换什么;对于某些类型的
T
,每个都实现了
ConverterInterface
,但您不知道列表中任何特定项的
T
是什么


testList[0]
(假设列表至少有一项)可以实现
ConverterInterface
、或
ConverterInterface
、或
ConverterInterface注意:这些对象必须存储在列表中,因为我使用它们的方式是在运行时创建的。我很清楚,直接访问对象会得到我想要的结果,但这不是我的问题。我将这些对象存储在列表中,因为它们是在运行时创建的。我正在开发一个Android模块,其中包含一个处理可编程交互的服务。我试图找出一种方法,让库的用户可以创建他们的BLE periphial属性,将它们提供给服务,然后当服务读取或写入字节时,它将为用户转换,而不必硬编码实现。(基本上,当读取某个内容时,会附带一个id,用于查找正确的转换对象)我想我不得不放弃这个想法。我只是找不到任何方法让它工作或者至少安全地工作。我仍然不确定需要什么,但正如我所说的,可能有一些方法可以跟踪所涉及的类型-例如,不需要列表,您可以有一个从类对象到处理该类的转换器的映射。或者,您可以向转换器添加一个getter方法,该方法返回相关的类对象。您可能仍然需要告诉编译器忽略不安全的强制转换,但在这种情况下,您可以确保它始终可以工作。最大的问题是,正在创建的转换器不是万能的。很可能会有多个相同类型的转换器。转换器将具有一个id,用于从列表中查找正确的转换器。所以从理论上讲,演员阵容应该总是成功的,如果不是的话,那将是程序员的错,这是可能的。但是有一段很长的历史,程序员认为他们比编译器更了解,并且被证明是错误的…(例如,IIRC JetBrains对
!!
操作符的使用做了一些研究,它告诉编译器“啊,但我知道这永远不会是空的。老实说,相信我!”,并发现令人惊讶的是,该值始终是空的。我相信在类型转换时也会发生类似的情况。)