5

Assumere il seguente codice:Come passare un parametro di tipo ad un riferimento generico della classe di costruzione?

class ConstructMe<T> {} 
data class Test<T> constructor(var supplier:() -> ConstructMe<T>) {} 

fun main(args: Array<String>) { 
    works<Int>() 
    breaks<Int>() 
} 

fun <T> works() { 
    Test<T>({ ConstructMe<T>() }) // (1) any one class type parameter can be removed like: 
    Test({ ConstructMe<T>() }) // (2) still works (class type inferred by argument type) 
    Test<T>({ ConstructMe() }) // (3) still works (argument type inferred by class type) 
} 

fun <T> breaks() { 
    Test<T>(::ConstructMe) // type interference failed (should probably work like (3); compiler improvement possible?) 
    Test<T>(::ConstructMe<T>) // type interference failed & type argument not allowed (language change necessary?) 
} 

Ho eseguito in questo passando proprietà JavaFX (SimpleIntegerProperty, SimpleStringProperty, ... e SimpleObjectProperty<T>) per un generico costruttori della classe () -> Property<T> argomento, dove passando ::SimpleIntegerProperty opere senza un problema , mentre ::SimpleObjectProperty ha esito negativo come il precedente codice di esempio.

È possibile migliorare qui il compilatore o consentire il passaggio dei parametri di tipo ai riferimenti di funzione/costruttore? Ha senso usare i riferimenti del costruttore su semplici espressioni lambda qui? Compila in modo diverso?

risposta

2

Sì, è possibile migliorare il compilatore qui. Potrebbe inferire il parametro di tipo per ConstructMe. Vedere il numero https://youtrack.jetbrains.com/issue/KT-10711.

Per la funzione di ricerca non in linea (in questo caso è il costruttore di Test) non c'è differenza tra lambda e callable di riferimento al costruttore. Per entrambi i casi il compilatore crea una classe anonima che ha il metodo invoke che crea un'istanza di ConstructMe.

Ma il riferimento callable è più conveniente di lambda nei casi in cui il costruttore abbia molti parametri.