Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有in的Kotlin泛型在编译时产生类型不匹配_Kotlin - Fatal编程技术网

具有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.进程(数据容器(“进程