我正在尝试创建一个类,该类通过一个接口具有两个重写函数。接口将采用通用类型,我希望函数可以简单地进行转换。
但是,当我创建这些对象的多个并将它们放入列表并单数访问它们时,我已经能够做到这一点,然后应将通用类型作为输入的函数会产生错误:{{1 }}
换句话说:
Type mismatch: inferred type is Any but Nothing was expected
这在首次实施时确实有效:
interface ConverterInterface<T>{
fun sender(value: T): ByteArray
fun receiver(bytes: ByteArray): T
}
但是,我想存储这些对象的列表并在以后访问。
class TestClass {
val objA = object: ConverterInterface<String>{
override fun sender(value: String): ByteArray {
//...
}
override fun receiver(bytes: ByteArray): String {
//...
}
}
}
我必须对列表类型使用通配符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 */
}
,因为如果尝试使用*
,则会收到类型推断失败错误。为了使它起作用,我可以将类型设置为Any
,但这不能解决任何问题,只会使out Any
函数起作用。
我觉得我想做的事情可能无法实现。简而言之,我希望无需进行类型转换即可访问这些功能。
答案 0 :(得分:1)
我认为您必须在这里进行一些重新设计。编译器会警告您代码中存在严重的类型安全问题,如果您未正确修复它,它很可能会再次咬住您。
您有List
个转换器,但您无法说出每个转换器可以转换的内容;每个人都为{em> some 类型ConverterInterface<T>
实现T
,但是您不知道列表中任何特定项目的T
是什么。
testList[0]
(假设列表中至少包含一项)可以实现ConverterInterface<String>
或ConverterInterface<Int>
或ConverterInterface<Map<URL, LinkedList<LinearGradientPaint>>
或其他任何方法。因此,testList[0].realSender("")
并不安全,因为它可能不接受字符串。
这就是编译器抱怨的原因;它对所涉及的类型一无所知,因此必须假设最坏的情况,并禁止调用。否则,当转换器无法处理您传递的参数类型时,您将在运行时冒ClassCastException
的风险。
更糟糕的是,由于类型擦除,您也无法在运行时找到该类型。 (在运行时,编译器完成魔术之后,只有一个简单的ConverterInterface
。)
顺便说一句,realSender()
的答案并不能解决这个问题,只是告诉编译器关闭它。它在运行时仍然会咬你。
因此,我认为您需要更仔细地考虑您要在此处实现的目标。
为什么要将这些转换器存储在列表中,为什么需要以这种方式访问它们?
如果您知道每个实现都可以接受String,则将列表设为List<ConverterInterface<String>>
:编译器将确保列表中的所有内容都可以使用String,然后可以安全地将String传递给任何列表中的转换器。
但是,如果列表中可能包含不同类型的转换器,那么您如何知道正在查看的转换器可以采用任何特定类型?即使该代码现在可以使用,仍然存在稍后会在列表中插入多余项并弄乱内容的风险。因此,您必须另辟track径。而另一种方式可能会为您提供更好的(类型安全)访问方式。
答案 1 :(得分:0)
我不确定这是否是一个好的解决方案,但这是我想出的。我创建了一个抽象类,该类不仅实现了该接口,而且还为发件人提供了预定义的函数,该函数在内部强制转换为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())
}
我知道该函数现在可以接受放入其中的任何内容,并且这可能会导致异常,但是到目前为止,我只能将其作为解决方案。另外,至少就我而言,该类的函数除其泛型外不应接收任何其他信息,因此传入的其他类型的值确实是个例外。