首页 \ 问答 \ Kotlin的逆差异(Contravariance in Kotlin)

Kotlin的逆差异(Contravariance in Kotlin)

我从来没有真正理解Java中的泛型,所以Kotlin似乎就是这种情况。 考虑以下代码片段(这是一个人为的例子):

class AnyComparator: Comparator<Any> {
    override fun compare(o1: Any, o2: Any): Int {
        TODO("not implemented")
    }
}


fun <T> test() {
    val x: Comparator<in Double> = AnyComparator() // OK!
    val y: Comparator<in T> = AnyComparator() // Compilation error
}

第二个赋值因错误而失败

Type mismatch. 
Required: kotlin.Comparator<in T>
Found: AnyComparator

现在,如果我理解正确的in修饰符表明T只被泛型类型Comparator (它产生逆变),那么我应该能够为任何Comparator分配类型参数E ,它是T的基类。 基于此,我应该能够将AnyComparator分配给变量xy ,因为Any类型是Kotlin中每个类的基类。 事实证明我不能,我不明白为什么。


I never truly understood generics in Java, so it seems to be the case with Kotlin. Consider the following code snippet (it's a contrived example):

class AnyComparator: Comparator<Any> {
    override fun compare(o1: Any, o2: Any): Int {
        TODO("not implemented")
    }
}


fun <T> test() {
    val x: Comparator<in Double> = AnyComparator() // OK!
    val y: Comparator<in T> = AnyComparator() // Compilation error
}

The second assignment fails with the error

Type mismatch. 
Required: kotlin.Comparator<in T>
Found: AnyComparator

Now, if I understand correctly the in modifier indicates the T is only consumed by the generic type Comparator (it makes contravariant), so I should be able to assign any Comparator with type argument E which is the base class of T. Based on this, I should be able to assign AnyComparator to both variables x and y, since the type Any is the base class of every class in Kotlin. It turns out I can't, and I don't understand why.


原文:https://stackoverflow.com/questions/44861928
更新时间:2020-01-12 04:35

最满意答案

它可能看起来很奇怪,但Any不是所有kotlin类的超类,而只是不可为空的类。 所有Kotlin课程的真正超类是Any? (它也是Any的超类)。

test函数中的泛型类型T没有上限,因此它可以是一个可为空的对象Any? 。 错误是因为当您需要Comparator<Any?>时,您不能使用Comparator<Any> Comparator<Any?>

因此,您可以修复将T上限定义为Any示例:

fun <T: Any> test() {
    //...
}

It can be seem strange but Any is not the superclass of all kotlin classes but only of not nullable classes. The real superclass of all Kotlin classes is Any? (it is also a superclass of Any).

The generic type T in your test function has no upper bound so it can be a nullable object Any?. The error is because you can't a Comparator<Any> when you need a Comparator<Any?>.

So you can fix your example defining the T upper bound as Any:

fun <T: Any> test() {
    //...
}
2017-07-01

相关问答

更多

Kotlin / Native本身可用吗?(Is Kotlin/Native usable by itself?)

Kotlin / Native被编译为纯本机代码,并且在没有JVM的情况下运行。 Kotlin / Native中的函数调用没有额外的开销。 Kotlin/Native is compiled to pure native code and runs without a JVM. There is no extra overhead for function calls in Kotlin/Native.

Kotlin递归(Kotlin recursion)

我将开始说tailrec关键字仅用作编译器的优化,它将尝试用循环表示函数而不用递归来避免堆栈溢出的风险。 如果我们避免递归,函数可能会看起来像这样: fun fact(x: Int): Int { var result = x for (i in x - 1 downTo 1) { result *= i } return result } I'll start saying that the tailrec keyword is used o ...

在Kotlin之前(before in Kotlin)

您可以使用Spark中的路径*来匹配所有路径,如下所示: before("*", { req, res -> logger.info("${req.requestMethod().toUpperCase()} ${req.fullUri()} by ${req.ip()} (${req.userAgent()})") }) // or: before("*") { req, res -> // ... You can use the path * in Spark to match ...

Kotlin的逆差异(Contravariance in Kotlin)

它可能看起来很奇怪,但Any不是所有kotlin类的超类,而只是不可为空的类。 所有Kotlin课程的真正超类是Any? (它也是Any的超类)。 test函数中的泛型类型T没有上限,因此它可以是一个可为空的对象Any? 。 错误是因为当您需要Comparator<Any?>时,您不能使用Comparator<Any> Comparator<Any?> 。 因此,您可以修复将T上限定义为Any示例: fun <T: Any> test() { //... } It can be seem ...

平等在Kotlin(Equality in Kotlin)

缺省值equals您描述的实现仅存在于数据类中。 不适用于从Object继承实现的常规类,并且使对象与自身相等。 The default equals implementation you're describing exists only for data classes. Not for regular classes where the implementation is inherited from Object, and just make the object equal to its ...

Mutidex和Kotlin(Mutidex and Kotlin)

尝试使用multiDexKeepFile api android { buildTypes { debug { ... multiDexEnabled true multiDexKeepFile file('multidex_keep_file.txt') } } } 其中multidex_keep_file.txt是每行单个类的文件,需要显式添加到主dex kotlin/r ...

使用Kotlin和Gradle(using Kotlin with Gradle)

这些类是Kotlin编译器的直接输出,之后应由Gradle打包到JAR中。 要构建JAR,您可以像在Java项目中一样运行jar任务: gradle jar 由于任务依赖性,此任务通常gradle build期间运行。 这将把Kotlin类打包成一个JAR存档(与其他JVM类一起,如果你有一个多语言项目),通常位于build/libs/ yourProjectName .jar 。 关于运行JAR,请参阅此问答以获取详细说明:( 链接) Thanks for @hotkey answer, it ...

Kotlin - forEach(Kotlin - forEach)

forEach将每个元素放在k并执行您指定的操作。 在您的示例中,“ what ”参数是::println ,它引用stdlib函数println(message: Any) 。 ::引入了对此函数的函数引用 。 每个元素作为参数message给println ,因此它将被打印在控制台上。 为了更清楚,你可以传递一个lambda而不是像这样的函数引用: k.forEach{ println(it) } forEach takes each element in k and does wha ...

如何指定Kotlin版本?(How to specify Kotlin version?)

用于此目的的命令行参数是-language-version ,其值应该是major.minor Kotlin发行版本,目前只有两个版本:1.0和1.1。 kotlinc -language-version 1.0 source.kt 要在IntelliJ IDEA中进行分析,请注意要编译源的版本,您可以创建一个方面(项目设置 - >构面 - >“+”)并在下拉列表中选择语言版本。 The command line argument for this purpose is -language-ve ...

可以在Grails中使用Kotlin吗?(Is it possible to use Kotlin in Grails?)

因此可以在Grails应用程序中编写Kotlin代码吗? 当然。 您可以使用Grails应用程序中的任何JVM语言。 我在Grails中用Kotlin构建了一个概念证明,并且所有的工作都像人们希望的那样工作: https : //github.com/jeffbrown/langdemo Is it therefore possible to write Kotlin code in a Grails application? Definitely. You can use any JVM lan ...

相关文章

更多

最新问答

更多
  • 如何保护Solr只允许SELECT请求给用户并禁止其他任何东西?(How to secure Solr to allow SELECT request to only users and disallow anything else?)
  • XPath表达式无效/错误TFHpple SWIFT 1.2(XPath Expression not working/incorrect TFHpple SWIFT 1.2)
  • css3 3D变换不能平滑地制作动画(css3 3D transform doesn't animate smoothly)
  • 运行时错误'91'和Outlook.Application = <对象变量或没有设置块变量>?(Run-time error '91' & Outlook.Application = Object variable or With block variable not set?)
  • 慢的webservice问题(Slow webservice problem)
  • textview的不正确对齐方式(Improper alignment of a textview)
  • 在第一步“Hello World”中出现Java错误(Cannot run “Hello World” program in Eclipse)
  • 为什么十六进制地址是14个字符?(why the hex address is 14 character?)
  • 如何在Python中的不同类中使用变量?(How to use variable in different classes in Python?)
  • asp:GridView HYPERLINKFIELD - datanavigateurlformatstring中的asp代码(asp:GridView HYPERLINKFIELD - asp code inside datanavigateurlformatstring)
  • 关于adaboost算法(About adaboost algorithm)
  • 在Matlab上内置图像(Built in Images on Matlab)
  • java swing:输入键事件时焦点丢失(java swing: Focus lost on enter key event)
  • C#中的通用约束,T是相同的TSomethingElse,对吧?(Generic constraints in C#, T is the same TSomethingElse, right?)
  • 从mybatis中的光标获取数据(Fetching data from cursor in mybatis)
  • 在运行时从XML构建对象的最佳方法(Best way for building objects out of XMLs at runtime)
  • 在整个窗口中拉伸sf :: Sprite(Stretch sf::Sprite across entire window)
  • Selenium Node API Web驱动程序等待超时处理程序(Selenium Node API web driver wait timeout handler)
  • 函数使用并且是map的一部分(循环依赖?)(Function uses and is part of map (circular dependency?))
  • 是否可以在C ++ 14中使用可选模板参数创建类型元组?(Is possible to make a tuple of types with optional template parameters in C++14?)
  • PHP从窗帘后面打印/ f(PHP prints /f from behind the curtains)
  • JFrame的contentPane的LayoutManager(LayoutManager of JFrame's contentPane)
  • 用于Instagram Feed的图像滚动(Image Roll Overs for Instagram Feed)
  • 如何显示拉伸字体(双倍宽度/高度)?(How to display stretched font (double width/height)?)
  • 文件操作API在fileapi.h和stdio.h中的WP8差异?(WP8 differences between file manipulation APIs in fileapi.h and stdio.h?)
  • 保存失败后Rails没有回滚事务()(Rails not rolling back transaction after failed save())
  • jqgrid中的分页问题与数组数据(Pagination problem in jqgrid with array data)
  • 重定向时,通过其他页面上的URL调用javascript函数(Call javascript function through url on otherpage while Redirecting)
  • 如何使用InvokeCommandAction调用我的方法并传入参数?(How do I go about using InvokeCommandAction to call a method of mine and pass in parameters?)
  • Jquerymobile按钮仅显示页面的第一个外观(Jquerymobile buttons are shown only first apperance of the page)