具有in的Kotlin泛型在编译时产生类型不匹配
我正在处理一个带有泛型的代码,当我在中使用具有in的Kotlin泛型在编译时产生类型不匹配,kotlin,Kotlin,我正在处理一个带有泛型的代码,当我在中使用时,我在编译时遇到了类型不匹配的问题 代码如下: open class A class B:A() data class DataContainer(val a:String, val b:A) interface Repo<T:A>{ fun setParam(param:T) fun getParam():T } abstract class RepoImp<T:
时,我在编译时遇到了类型不匹配的问题
代码如下:
open class A
class B:A()
data class DataContainer(val a:String,
val b:A)
interface Repo<T:A>{
fun setParam(param:T)
fun getParam():T
}
abstract class RepoImp<T:A>:Repo<T>{
private lateinit var parameter:T
override fun setParam(param: T) {
parameter = param
}
override fun getParam(): T {
return parameter
}
}
class BRepo:RepoImp<B>()
class Repo2(val repo: Repo<in A>){
fun process(b:DataContainer){
repo.setParam(b.b)
}
}
val repoB = BRepo()
val repo2 = Repo2(repoB)// Here I got: Type mismatch: inferred type is BRepo but Repo<in A> was expected
开放式A类
B类:A()
数据类DataContainer(val a:String,
(b:A)
接口回购{
fun setParam(参数:T)
fun getParam():T
}
抽象类RepoImp:Repo{
私有lateinit变量参数:T
覆盖fun setParam(参数:T){
参数=参数
}
重写fun getParam():T{
返回参数
}
}
BRepo类:RepoImp()
第2类回购(增值回购:回购){
有趣的过程(b:数据容器){
回购设定参数(b.b)
}
}
val repoB=BRepo()
val repo2=repo2(repoB)//这里我得到了:类型不匹配:推断的类型是BRepo,但应该是Repo
我还尝试将属性repo从Repo2更改为repo,因为BRepo是repo
,它不是repo
,(但它会满足repo
)
换句话说,Repo
必须能够接受setParam(a())
,但BRepo.setParam()
只能接受B或B的子类
或者换句话说,BRepo
是一种Repo
,在写入值时,它对类型的限制比Repo
更严格(但在读取值时限制更宽松)
classrepo2(val-repo:repo)
不起作用的原因是repo
本质上是一个repo
。不能使用任何类型的对象对Repo
调用setParam()
您的代码中有一个设计缺陷,您不能简单地通过更改Repo2的构造函数签名来修复它。现在,Repo2需要能够向传递给它的对象写入A,而BRepo根据定义不支持写入A,只支持写入B。您将需要使至少一个类的定义在类型方面更加灵活
更常见的类可能更容易理解协方差限制:
val stringList: MutableList<String> = ArrayList()
var anyList: MutableList<in Any> = ArrayList()
anyList.add(5) // ok
anyList = stringList // Compiler error.
// You wouldn't be able to call add(5) on an ArrayList<String>
val-stringList:MutableList=ArrayList()
var anyList:MutableList=ArrayList()
anyList.add(5)//确定
anyList=stringList//编译器错误。
//您将无法在ArrayList上调用add(5)
基本上,MutableList
不是一个MutableList
,同样的Repo
也不是一个Repo,因为BRepo是一个Repo
,所以它不是Repo
,(但它会满足Repo
)
换句话说,Repo
必须能够接受setParam(a())
,但BRepo.setParam()
只能接受B或B的子类
或者换句话说,BRepo
是一种Repo
,在写入值时,它对类型的限制比Repo
更严格(但在读取值时限制更宽松)
classrepo2(val-repo:repo)
不起作用的原因是repo
本质上是一个repo
。不能使用任何类型的对象对Repo
调用setParam()
您的代码中有一个设计缺陷,您不能简单地通过更改Repo2的构造函数签名来修复它。现在,Repo2需要能够向传递给它的对象写入A,而BRepo根据定义不支持写入A,只支持写入B。您将需要使至少一个类的定义在类型方面更加灵活
更常见的类可能更容易理解协方差限制:
val stringList: MutableList<String> = ArrayList()
var anyList: MutableList<in Any> = ArrayList()
anyList.add(5) // ok
anyList = stringList // Compiler error.
// You wouldn't be able to call add(5) on an ArrayList<String>
val-stringList:MutableList=ArrayList()
var anyList:MutableList=ArrayList()
anyList.add(5)//确定
anyList=stringList//编译器错误。
//您将无法在ArrayList上调用add(5)
基本上MutableList
不是MutableList
同样Repo
也不是Repo
Repo2
类希望只使用类型a
,使用Repo2(val-Repo:Repo)
开放式A类
B类:A()
C类:A()
D类:A()
BRepo类:RepoImp()
CRepo类:RepoImp()
DRepo类:RepoImp()
接口回购{
fun setParam(参数:T)
fun getParam():T
}
抽象类RepoImp:Repo{
私有lateinit变量参数:T
覆盖fun setParam(参数:T){
参数=参数
}
重写fun getParam():T{
返回参数
}
}
第2类回购(增值回购:回购){
有趣的过程(b:数据容器){
回购设定参数(b.b)
}
}
数据类数据容器(
瓦尔:字符串,
瓦尔b:T
)
主要内容(){
val repoB=BRepo()
val repoC=CRepo()
val repoD=DRepo()
val repo2=repo2(repoB)
val repo3=Repo2(repoC)
val repo4=Repo2(repoD)
repo2.process(数据容器(“process B type”,B()))
repo3.process(数据容器(“process C type”,C()))
repo4.process(数据容器(“process D type”,D()))
println(repo2.repo.getParam())
println(repo3.repo.getParam())
println(repo4.repo.getParam())
}
该Repo2
类预期只使用类型A
,使用Repo2(val-repo:repo)
开放式A类
B类:A()
C类:A()
D类:A()
BRepo类:RepoImp()
CRepo类:RepoImp()
DRepo类:RepoImp()
接口回购{
fun setParam(参数:T)
fun getParam():T
}
抽象类RepoImp:Repo{
私有lateinit变量参数:T
覆盖fun setParam(参数:T){
参数=参数
}
重写fun getParam():T{
返回参数
}
}
第2类回购(增值回购:回购){
有趣的过程(b:数据容器){
回购设定参数(b.b)
}
}
数据类数据容器(
瓦尔:字符串,
瓦尔b:T
)
主要内容(){
val repoB=BRepo()
val repoC=CRepo()
val repoD=DRepo()
val repo2=repo2(repoB)
val repo3=Repo2(repoC)
val repo4=Repo2(repoD)
repo2.进程(数据容器(“进程