如果我使用 Set 接口参考,我尝试调用 add 方法,我会得到一个未解决的引用错误:
fun main(args : Array<String>) {
val set = HashSet<Integer>()
set.add(Integer(1)) //OK
val seti : Set<Integer> = HashSet<Integer>()
seti.add(Integer(2)) //FAILING: Unresolved reference to add**
}
我不明白那种行为。 Java Set 接口有一个 add 方法,我希望Kotlin可以作为扩展版本而不是更少的方法。
PD1:我在Idea IDE中遇到了同样的错误或使用gradle构建。 PD2:使用kotlin 1.0.0-beta-4584
答案 0 :(得分:6)
Kotlin将Java的Set
接口分为两个接口:Set
和MutableSet
。后一个接口声明了变异方法,例如您正在寻找的add
方法。
通常,MutableSet
等接口扩展Set
接口,HashSet
等实现实现MutableSet
接口。然后可以使用Set
接口传递只读实例,以帮助避免发生常见错误。
答案 1 :(得分:1)
关于代码的一些注意事项,请参阅@nhaarman's answer有关Set
接口以及编译器错误的原因。 此回答纯粹是为了获取更多信息:
首先,您可以使用hashSetOf()
函数而不是HashSet
构造函数,尽管使用构造函数很好,但它不常见。
val mySet = hashSetOf<Int>()
您应该使用Int
代替Integer
。你没有收到编译器警告,因为你应该让Kotlin决定何时讨论Int
,Long
,Byte
等原语或类。不要忽略那个警告。文档中的table for mapped types可能并不清楚它适用于相同类型的原始和盒装版本,除非您需要原始数组,否则不必担心使用哪个。
不要实例化Integer
类,例如调用Integer(1)
或Int(1)
的代码。相反,使用类似下面的代码 - 它让Kotlin为你做拳击:
val mySet1 = hashSetOf(1, 2, 3) // makes a HashSet<Int> which in Java is HashSet<Integer>
val mySet2 = hashSetOf<Int>() // makes a HashSet<Int> which in Java is HashSet<Integer>
mySet2.add(1)
mySet2.add(2)
mySet2.add(3)
如果你想在将构建的构建包装到构造中并返回readonly接口时初始化一个集合,那么你有很多选择。其中一些是:
val mySet: Set<Int> = hashSetOf<Int>().apply {
// do logic that adds to set (`this` is the set)
}
或:
val mySet: Set<Int> = run {
val tempSet = hashSetOf<Int>()
// do logic that adds to set
tempSet
}
或:
val mySet = someFunc()
fun someFunc(): Set<Int> {
val tempSet = hashSetOf<Int>()
// do logic that adds to set
return tempSet
}
查看功能文档:apply(),let(),run()和with()
我在自己的库中有一个相当无用的扩展函数,当我想要一个只读接口时,它会清楚,因为强制转换会产生警告,而且我并不总是想在声明中指定冗余类型。为了便于阅读,它是一个扩展:
@Suppress("USELESS_CAST")
fun <T: Any> MutableSet<T>.readonly(): Set<T> = this as Set<T>
用法是:
val mySet = hashSetOf<Int>().apply {
// logic that builds the set
}.readonly()
// inferred type of mySet is Set<Int>