在以下代码"Happy Halloween!"
中,42
等标记为"类型不匹配。" (必需:T,Found:String(或Int))但编译器是否应该能够从类型检查中推断返回值的类型是否正确?
interface Type<T>
class StringType() : Type<String>
class IntType1() : Type<Int>
class IntType2(val a: Int, val b: Int) : Type<Int>
fun <T> something(type: Type<T>): T = when (type) {
is StringType -> "Happy Halloween!"
is IntType1 -> 42
is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b
else -> throw IllegalArgumentException()
}
答案 0 :(得分:1)
你可以这样写:
display: inline-block
运行以下内容:
interface Type<T>
class StringType() : Type<String>
class IntType1() : Type<Int>
class IntType2(val a: Int, val b: Int) : Type<Int>
inline fun <reified T> something(type: Type<T>): T {
val result = when(type) {
is StringType -> "Happy Halloween"
is IntType1 -> 42
is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b
else -> throw IllegalArgumentException()
}
return if (result is T) result else throw Exception()
}
会给你这个输出:
fun main(args: Array<String>) {
println(something(StringType()))
println(something(IntType1()))
println(something(IntType2(2, 3)))
}
在此处详细了解内联函数和已知参数:Reified type parameters。
答案 1 :(得分:0)
当编译器应用类型擦除时,将定义返回类型。所以,让我们说,你使用一个字符串......你的方法就像:
fun something(type: Type<String>): String = when (type) {
is StringType -> "Happy Halloween!"
is IntType1 -> 42 //Wrong: you must return String!
is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b
else -> throw IllegalArgumentException()
}
这是:你必须在编译时知道你的返回类型。如果你不知道这一点,你必须告诉编译器:
fun <T> something(type: Type<T>): Any = when (type) {
is StringType -> "blabla"
is IntType1 -> 42
is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b
else -> throw IllegalArgumentException()
}
很抱歉这段代码不是你跳的,你会在返回方法后进行演员表...
但你可以这样:
fun <T> something(type: Type<T>): T = when (type) {
is StringType -> type.b
//is IntType1 -> 42 remove this!
is IntType2 -> type.a * type.a + type.b * type.b + type.a * type.b
else -> throw IllegalArgumentException()
}
假设type.a和type.b被参数化为T.那么你的代码就可以了。
答案 2 :(得分:0)
如果我简化你的例子:
interface Type<T>
fun <T> something(type: Type<T>): T = when (type) {
is Type<String> -> "Happy Halloween!"
else -> throw IllegalArgumentException()
}
编译器现在抱怨他:cannot check for instance of erased type
所以问题是因为类型擦除在运行时Type<String>
和Type<Int>
之间没有区别,所以编译器不允许这样做。
您可以尝试使用像Gson TypeToken<T>
或Jackson TypeReference<T>
这样的内容
文档引用此博客文章解释了这个想法:http://gafter.blogspot.ca/2006/12/super-type-tokens.html
答案 3 :(得分:0)
>>> a = np.random.randint(1, 10, size=(1000,))
>>> %timeit concatenated_ranges(a)
10000 loops, best of 3: 142 us per loop
>>> %timeit concatenated_ranges2(a)
10000 loops, best of 3: 72.6 us per loop
运算符与Java的is
运算符非常相似,在运行时执行。
因此,在编译时,编译器不知道实际类型,因此会出现编译错误。
这是另一个简单的例子:
instanceof