2016-01-27 20 views
5

Se io uso un Set di riferimento interfaccia e provo a chiamare aggiungere metodo ottengo un errore riferimento non risolto:errore di riferimento non risolti durante la chiamata aggiungere metodo Kotlin interfaccia Set

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

non lo faccio capisci che comportarsi Java L'interfaccia ha un , aggiungere il metodo e mi aspettavo che Kotlin uno fosse una versione estesa e non avesse meno metodi.

PD1: Ottengo lo stesso errore in Idea IDE o edificio con gradle. PD2: Usando Kotlin 1.0.0-beta-4584

risposta

6

Kotlin separa l'interfaccia di Java Set in due interfacce: Set e MutableSet. Quest'ultima interfaccia dichiara metodi di muting come il metodo add che stai cercando.

Generalmente, interfacce come MutableSet estendere l'interfaccia Set e implementazioni come HashSet implementano l'interfaccia MutableSet. L'interfaccia Set può quindi essere utilizzata per aggirare un'istanza di sola lettura, per evitare che si verifichino errori comuni.

1

Alcune note sul codice, vedere @nhaarman's answer sull'interfaccia Set e sul perché si è verificato l'errore del compilatore. Questa risposta è puramente per ulteriori informazioni:

In primo luogo, è possibile utilizzare hashSetOf() funzione invece di costruttore HashSet, anche se utilizzando il costruttore va bene è solo meno comune.

val mySet = hashSetOf<Int>() 

Si consiglia di utilizzare Int invece di Integer. Hai ricevuto un avviso del compilatore quando non lo facevi perché dovresti lasciare che Kotlin decidesse quando parla di primitive o classi per Int, Long, Byte, ecc. Non ignorare questo avviso. Il table for mapped types nella documentazione potrebbe non essere chiaro che si applica alla versione primitiva e in scatola dello stesso tipo e, a meno che non sia necessario disporre di matrici primitive, non preoccuparsi di quale viene utilizzato.

Non istanziare classi Integer come la chiamata di codice Integer(1) o Int(1). Invece, usare qualcosa come il seguente codice - si è lasciare Kotlin fare la boxe per voi:

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) 

E se si desidera inizializzare un set mentre avvolgendo la costruzione del set per la costruzione e il ritorno l'interfaccia di sola lettura allora hai molte opzioni.Alcuni dei quali sono:

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

o:

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

o:

val mySet = someFunc() 

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

vedi Documentazione per le funzioni: apply(), let(), run() e with()

I avere una funzione di estensione abbastanza inutile nelle mie librerie che chiarisce quando voglio un'interfaccia readonly poiché casting genera un warning e non sempre voglio specificare il tipo ridondante nella dichiarazione. Si tratta di un'estensione per il bene di leggibilità:

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

L'utilizzo è:

val mySet = hashSetOf<Int>().apply { 
    // logic that builds the set 
}.readonly() 

// inferred type of mySet is Set<Int> 
Problemi correlati