修正genericstypes到第一个参数的types
我想写一个扩展函数,它将在任何types和接受相同types或子types的参数,但不是一个完全不同的types。
我尝试过天真的做法,但没有奏效:
fun Tf(x: T) { } fun main(args: Array) { "1".f("1") // ok "1".f(1) // should be error }
看来,编译器只是使用任何的T我想T被固定为接收器types。
唯一的方法就是要告诉编译器你想要什么。
fun Tf(x: T) { }
为了使用它,你必须告诉Kotlin你想要的types是什么。
"1".f("2") // Okay "1".f(2) // Okay (see voddan's answer for a good explanation) "1".f (2) // Fails because 2 isn't a String "1".f(2) // Fails because "1" isn't an Int
当你像"1".f(1)
那样调用fun
,编译器寻找一个普通的超types的String
和Int
,它是Any
。 然后它决定T is Any
,并且没有错误。 影响此过程的唯一方法是明确指定T
: "1".f
由于所有的检查都是由编译器执行的,这个问题与types擦除无关。
你的问题就像是说:“ 约翰比卡尔大3岁,卡尔比约翰小3岁 ”……你还不知道他们的年龄,没有更多的信息。 这是你给编译器的证据types,然后你期望它能正确猜测。 从这些信息中唯一可以得出的结论是,约翰至少3岁,卡尔至少1岁。
这种types的假设就像编译器findAny
的共同上限一样。 它有两种强烈的文字types可供选择,而且无法改变。 如何判断Int
或String
是否更重要,同时你告诉它任何T
的上界都是Any?
根据您的型号规格是有效的。 所以安全的答案是看文字是否符合T: Any?
的标准T: Any?
当然他们也有,他们都有祖先的Any
。 即使你不想要,编译器也能满足你所有的条件。
如果你有打破平局的标准,这将有所不同。 例如,如果返回types为T
,而types为String
的variables接收该值,则会影响Type推断的决定。 这例如产生一个错误:
fun T.f2(x: T): T = x val something: String = "1".f2(1) // ERROR
因为现在typesT
被锚定在expressionString
的“左侧”,毫无疑问。
也有可能这也可能是一个types推断问题,而不是打算,检查YouTrack中报告的问题或添加自己的从编译器团队得到明确的答案。 我添加了一个function请求KT-13138用于锚定特定的types参数,以了解团队如何响应。
您可以通过将f
为返回可调用对象的扩展属性来将T
修复为接收方types:
val Tf: (T) -> Unit get() = { x -> } fun main(vararg args: String) { "1".f("1") // will be OK once KT-10364 is resolved "1".f(1) // error: The integer literal does not conform to the expected type String }
不幸的是, "1".f("1")
目前会导致一个错误:“types不匹配:推断types是字符串,但T是预期的”。 这是一个编译器问题。 见KT-10364 。 另见KT-13139 。 您可以投票和/或观看更新的问题。 在解决此问题之前,您仍然可以执行以下操作:
"1".f.invoke("1") /* or */ ("1".f)("1") /* or */ val f = "1".f f("1")