在Kotlin Set界面中调用add方法时未解决的引用错误

时间:2016-01-27 12:17:35

标签: kotlin

如果我使用 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

2 个答案:

答案 0 :(得分:6)

Kotlin将Java的Set接口分为两个接口:SetMutableSet。后一个接口声明了变异方法,例如您正在寻找的add方法。

通常,MutableSet等接口扩展Set接口,HashSet等实现实现MutableSet接口。然后可以使用Set接口传递只读实例,以帮助避免发生常见错误。

答案 1 :(得分:1)

关于代码的一些注意事项,请参阅@nhaarman's answer有关Set接口以及编译器错误的原因。 此回答纯粹是为了获取更多信息:

首先,您可以使用hashSetOf()函数而不是HashSet构造函数,尽管使用构造函数很好,但它不常见。

val mySet = hashSetOf<Int>()

您应该使用Int代替Integer。你没有收到编译器警告,因为你应该让Kotlin决定何时讨论IntLongByte等原语或类。不要忽略那个警告。文档中的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>