Undefined reference error when calling the add method in the Kotlin Set interface

If I use the link to the Set interface and I try to call the add method, I get an unresolved link error:

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** } 

I do not understand this behavior. The Java Set interface has an add method, and I expected Kotlin to be an extended version and not have fewer methods.

PD1: I get the same error in the Idea IDE or using gradle. PD2: Using kotlin 1.0.0-beta-4584

+5
source share
2 answers

Kotlin splits the Java Set interface into two interfaces: Set and MutableSet . The final interface declares mutating methods, such as the add method you are looking for.

Typically, interfaces such as MutableSet extend the Set interface, and implementations like HashSet implement the MutableSet interface. The Set interface can then be used to pass a read-only instance to avoid accidental errors.

+6
source

For a few notes about your code, see @nhaarman's answer about the Set interface and why you got a compiler error. This answer is for more information:

First, you can use the hashSetOf() function instead of the HashSet constructor, although using the constructor is fine, it is less common.

 val mySet = hashSetOf<Int>() 

You should use Int instead of Integer . You got a compiler warning when you didn't, because you have to let Kotlin decide when it comes to primitives or classes for Int , Long , Byte , etc. Do not ignore this warning. the table for mapped types in the documentation may not be clear that it applies to the primitive and boxed versions of the same type, and if you don't need primitive arrays do not worry about what is used.

Do not instantiate Integer classes, such as calling Integer(1) or Int(1) code. Instead, use something like the following code - this allows Kotlin to make boxing for you:

 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) 

And if you want to initialize a collection by wrapping the construction of the collection in a construct and returning the readonly interface, you have many options. Some of them:

 val mySet: Set<Int> = hashSetOf<Int>().apply { // do logic that adds to set (`this` is the set) } 

or

 val mySet: Set<Int> = run { val tempSet = hashSetOf<Int>() // do logic that adds to set tempSet } 

or

 val mySet = someFunc() fun someFunc(): Set<Int> { val tempSet = hashSetOf<Int>() // do logic that adds to set return tempSet } 

see documents for functions: apply () , let () , run () and with ()

I have a pretty useless extension function in my own libraries that makes it clear when I want an interface to read, since a warning appears when creating a casting, and I don’t always want to specify an excess type in the declaration. This is an extension for readability:

 @Suppress("USELESS_CAST") fun <T: Any> MutableSet<T>.readonly(): Set<T> = this as Set<T> 

Using:

 val mySet = hashSetOf<Int>().apply { // logic that builds the set }.readonly() // inferred type of mySet is Set<Int> 
+1
source

Source: https://habr.com/ru/post/1241607/


All Articles