例如:
var a = true
val test = if (a) -1 else -3.2
我曾期望test
的类型应该是类型层次结构中最接近的交集,即Int和Double为Number
。
但是在IDE中,它似乎具有{Comparable<{ Double & Int }> & Number}
的类型。
而且很奇怪,我不能这样指定(由于{}是保留用于创建lambda的,所以只能将其设置为Number
类型。
另外一件奇怪的事情是,如果我尝试从Comparable接口中执行某些功能,则会引发一些错误:
// Warning at value 2
// The integer literal does not conform to the expected type {Double & Int}
test.compareTo(2)
3.compareTo(-1.1) // possible
2.3.compareTo(100) // possible
// But why not this is possible, while it has inferred type of Comparable?
test.compareTo(2)
有人可以帮助您理解这里的概念吗?还有几个问题:
问题1的答案是,编译器正在尽最大努力来推断类型,发明了新的约束条件来描述它。
问题2的答案是你不能。
问题3的答案是您不能,因为Int
与Double
不具有可比性,反之亦然。因此Comparable
中的所有方法实际上都不可用,但是该值肯定针对something实现了Comparable
。这对Comparable
没用,但可能对另一个接口有用。例如,假设:
interface ZeroAndComparable<T> {
fun compareTo(t: T): Int
fun zero(): T
}
val foo : ZeroAndComparable<Int> = someZeroAndComparableInt()
val bar : ZeroAndComparable<Double> = someZeroAndComparableDouble()
val foobar = if (a) foo else bar
val zero : Any = foobar.zero() // should work
foobar.compareTo(something) // cannot work
&
在这里表示交集类型(Kotlin语言本身不支持,但是编译器在内部使用它们)。您可以在[不完整] specification中看到它。
交集类型是特殊的不可表示的类型,用于表示一个值同时属于多种类型的事实。
“ Non-denotable”表示您无法指定该类型。我不确定,但我认为类型中多余的{
}
应该恰好表明了这一点。
特别是Comparable<Double & Int>
表示您只能将test
与both Double
和Int
进行比较,但没有此类值。
类型层次结构中最接近的交点,即
Int
和Double
的交点是Number
。
这是最小的上限,它更接近联合,而不是交集。
此最小上限不是Number
,因为它[[also占据了Comparable
接口的最小上限,因为Comparable<Double & Int>
是互变的:
Comparable
此计算实际上也在lub(Int, Double) = Number & lub(Comparable<Int>, Comparable<Double>) = Number & Comparable<Int & Double>
下进行了描述:
[所有并集类型在转换为可在Kotlin类型系统中表示的特定相交类型时,都会经历类型衰减。尽管规范对“联合类型”的使用是
不是标准之一。