fun <T: A()> getUtil(t: T): Util<T> = if (t is B) UtilB() else // ...
Kotlin编译器在这里发出警告(未检查的强制转换):
fun <T: A()> getUtil(t: T): Util<T> = if (t is B) UtilB() as Util<T> else // ...
据我所知,Kotlin smart cast应该知道utilb()作为util
由t is b
检查。
Java代码和编译器给出了完全相同的结果。
为了为每个实现获得正确的util类,我在伴生对象getUTIL
上创建了一个函数,该函数基于泛型类型T的参数为每个实现返回正确的util类,该参数扩展了a:T:a
,因此返回类型为util
。
但是,当我为A
的每个派生类编写函数体时,使用Is b
检查参数的类型,然后使用utilb()
返回正确的util时,Kotlin编译器在返回点给了我一个错误,说utilb
不属于util
类型,尽管它应该属于util
类型。
然后,我将utilb
强制转换为util
,这种方法起作用了,但给了我一个错误“unchecked cast”。根据我的理解,Kotlin smart cast应该能够确定它确实是一个有效的检查型cast(用检查的是b
),在运行快速测试后,它也是有效的...
我用Java重写了同样的代码,结果完全一样...
据我所知,这是Java/Kotlin泛型的一个限制。我想知道如何检查这个铸模。有可能吗?
abstract class A
class B : A()
class C : A()
abstract class Util<T : A> {
abstract fun getName(): String
companion object {
fun <T : A> getUtil(t: T): Util<T> = when(t) {
is B -> UtilB() as Util<T> // warning
is C -> UtilC() // this event gives an error
else -> throw IllegalArgumentException("No util for this class.")
}
}
}
class UtilB : Util<B>() {
override fun getName(): String = "B"
}
class UtilC : Util<C>() {
override fun getName(): String = "C"
}
fun main() {
val b = B()
val c = C()
val utilB = Util.getUtil(b)
val utilC = Util.getUtil(c)
println(utilB.getName()) // prints B
println(utilC.getName()) // prints C
}
以下是有效的修改版本:
abstract class A
class B : A()
class C : A()
abstract class Util<T : A> {
abstract fun getName(): String
companion object {
fun <T : A> getUtil(t: T): Util<A> = when(t) { // here return Util<A>
is B -> UtilB() // No need cast
is C -> UtilC()
else -> throw IllegalArgumentException("No util for this class.")
}
}
}
class UtilB : Util<A>() { // Replace B by A
override fun getName(): String = "B"
}
class UtilC : Util<A>() { // Replace C by A
override fun getName(): String = "C"
}
fun main() {
val b = B()
val c = C()
val utilB = Util.getUtil(b)
val utilC = Util.getUtil(c)
println(utilB.getName()) // prints B
println(utilC.getName()) // prints C
}
但我不确定你走的路是对的。当我看到这个模式时,我看到了密封的类。
下面是一个使用密封类的实现:
sealed class AA {
class BB : AA()
class CC : AA()
}
sealed class AAU {
abstract fun getName():String
class BBU : AAU() {
override fun getName()= "BB"
}
class CCU : AAU(){
override fun getName()= "CC"
}
}
fun getU(aa: AA) =
when(aa) {
is AA.BB -> AAU.BBU()
is AA.CC -> AAU.CCU()
}
fun main() {
val bb = AA.BB()
val cc = AA.CC()
val bbu = getU(bb)
val ccu = getU(cc)
println(bbu.getName())
println(ccu.getName())
}
sealed class AA {
class BB : AA()
class CC : AA()
}
fun getName(aa: AA) =
when(aa) {
is AA.BB -> "BB"
is AA.CC -> "CC"
}
fun main() {
val bb = AA.BB()
val cc = AA.CC()
println(getName(bb))
println(getName(cc))
}
我需要 Kotlin 中的一个集合来仅包含实现给定接口的元素。 例如:包含动物集合的地图: 通过阅读文档、博客和SO问题,我编写了使用Generics in关键字的代码: 现在我想在Test类中添加一个读取“data”内容的方法,例如将其打印到控制台: 如果我这样做,我会遇到编译错误: 我的解决方案是强制我的动物进入一个ArrayList 但是我不确定这是编写这种代码的最好方式。有没有更好的方式告
问题内容: 以下代码在t3行中出现编译错误: 错误消息是: 类型不匹配:无法从对象转换为T 我知道我可以使用强制转换或手动绑定来解决问题,我的问题是: 编译器进行自动绑定是否如此困难,是否会失败? 编辑:添加了错误消息。 编辑:添加了另一个示例如何不会发生该错误。 编辑:删除了第二个示例,因为它令人困惑,使问题更加清楚。 问题答案: 在第一种情况下,您有两个具有名为的类型参数的泛型方法,但是这些类
我有一个gradle 4.1多项目,其中包含一个包含2个子文件夹“api”和“实现”的“项目A”。 多项目使用在主build.gradle的子项目部分中定义的< code>kotlin和< code>java-library插件。实现项目具有对< code>:projectA:api的API依赖性 在api文件夹中,我在“src/main/java”中有kotlin和java文件,在实现项目中,我
因此,我有一些带有这些签名的Java方法(为了简单起见,删除了注释和代码体): 我在Kotlin中有一些代码,它调用了'join'方法: 例如,如果我想用“分隔符”参数调用后一个方法签名,问题就来了: 这段代码无法编译。编译器无法决定调用哪个方法。错误: 错误:(5,13)Kotlin:在未完成类型推断的情况下,无法在以下候选项中进行选择:public open fun join(vararg A
在stackoverflow中还没有讨论的情况下,我遇到了“不兼容类型”编译器错误(例如,为什么这个通用java代码不能编译?)。 我的期望很简单--我调用的是一个模板化方法,它不使用包含类的任何“泛型”类,因此它应该从方法参数中提取模板参数的类型,并且在所有情况下都应该编译--但我得到了“不兼容类型”编译器错误。 我注意到解决这个问题的奇怪方法--在方法参数中向泛型datatype添加“<?ex
这个问题已经被问了很多次了,即使是在经历了所有的解决方案之后,我也无法让hibernate validator工作。 控制器类:- servlet-上下文:- 依赖关系:- 验证类:- 我错过了什么?