在 Kotlin Set 接口中调用 add 方法时未解决的引用错误
Unresolved reference error while calling add method in Kotlin Set interface
如果我使用 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:使用科特林 1.0.0-beta-4584
Kotlin 将 Java 的 Set
接口分成两个接口:Set
和 MutableSet
。后一个接口声明了变异方法,例如您正在寻找的 add
方法。
通常,MutableSet
等接口扩展了 Set
接口,HashSet
等实现实现了 MutableSet
接口。然后 Set
接口可用于传递 read-only 实例,以帮助避免常见错误的发生。
关于您的代码的一些注意事项,请参阅 关于 Set
接口以及编译器错误的原因。 这个答案 纯粹是为了补充信息:
首先,您可以使用 hashSetOf()
函数代替 HashSet
构造函数,虽然使用构造函数很好,但不太常见。
val mySet = hashSetOf<Int>()
您应该使用 Int
而不是 Integer
。当您没有收到编译器警告时,因为您应该让 Kotlin 决定它何时谈论原语或 类 for 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)
如果你想初始化一个集合,同时将集合的构建包装到构造中并返回只读接口,那么你有很多选择。其中一些是:
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(), and 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>
如果我使用 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:使用科特林 1.0.0-beta-4584
Kotlin 将 Java 的 Set
接口分成两个接口:Set
和 MutableSet
。后一个接口声明了变异方法,例如您正在寻找的 add
方法。
通常,MutableSet
等接口扩展了 Set
接口,HashSet
等实现实现了 MutableSet
接口。然后 Set
接口可用于传递 read-only 实例,以帮助避免常见错误的发生。
关于您的代码的一些注意事项,请参阅 Set
接口以及编译器错误的原因。 这个答案 纯粹是为了补充信息:
首先,您可以使用 hashSetOf()
函数代替 HashSet
构造函数,虽然使用构造函数很好,但不太常见。
val mySet = hashSetOf<Int>()
您应该使用 Int
而不是 Integer
。当您没有收到编译器警告时,因为您应该让 Kotlin 决定它何时谈论原语或 类 for 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)
如果你想初始化一个集合,同时将集合的构建包装到构造中并返回只读接口,那么你有很多选择。其中一些是:
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(), and 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>