2015-11-14 9 views
10

Non riesco a capire il seguente pezzo di documentazione Kotlin:Perché il compilatore Kotlin richiede l'inizializzatore esplicito della proprietà var?

The initializer, getter and setter are optional. Property type is optional 
if it can be inferred from the initializer or from the base class member being overridden. 

Examples: 
var allByDefault: Int? // error: explicit initializer required, default 
getter and setter implied 

L'unica spiegazione del perché il compilatore richiede inizializzazione esplicita qui (almeno l'unica spiegazione che posso venire con) è che Kotlin non ha valori di default delle proprietà. È giusto? Se è così, perché? In altre parole: qual è la differenza tra le proprietà di Kotlin e i campi Java (che hanno valori predefiniti) che non ci permettono di avere valori predefiniti di proprietà?

risposta

7

Semplice: in Java i valori predefiniti sono 0 (zero) e null. Ma in Kotlin la maggior parte dei valori non è annullabile, quindi non è possibile inizializzarli con null. Per i valori primitivi potrebbe esserci una strategia predefinita di inizializzazione con zeri, ma non è stata fatta per essere coerente. Ma negli array primitivi il valore predefinito è zero.

Se hai davvero bisogno di quella semantica di inizializzazione, dai un'occhiata alle proprietà lateinit: https://kotlinlang.org/docs/reference/properties.html#late-initialized-properties.

Questo meccanismo consente fondamentalmente di inizializzare un campo con null, ma in seguito consente di annullare asserzioni nulle.

INOLTRE

realtà Kotlin è molto intelligente circa inizializzazione. Per esempio che funziona:

val x: Int 

if(something) 
    x = 1 
else 
    x = 2 

println(x) 

Qui kotlinc può proove che x viene inizializzato prima è in uso, in modo che il codice è OK

+1

"Ma in Kotlin maggior parte dei valori non sono annullabili, quindi non è possibile inizializzare con null" - I ha chiesto specificamente la proprietà dichiarata in questo modo: 'var allBeDefaut: Int?'.Chiaramente, questa è la variabile nullable e potrebbe essere inizializzata con 'null' di default, invece di, ad esempio,' var someVar: Int'. – aga

+0

@aga Ma la coerenza è molto importante. Inoltre, l'inizializzazione predefinita è in qualche modo indiretta/invisibile, ma dovrebbe essere comunque evitata. Quasi tutti i casi d'uso per questo hanno una soluzione più elegante – voddan

+0

E non ho mai visto un buon uso per l'inizializzazione di default, in qualsiasi lingua con cui ho lavorato – voddan

1

Kotlin non fa nulla implicitamente. Non converte i tipi numerici senza le tue istruzioni specifiche, né imposta un valore di default o di inizializzazione senza che sia esplicito. È una scelta progettuale per eliminare gli errori comuni rilevati nei tipici programmi Java. Non è chiaro al compilatore se hai dimenticato di inizializzarlo o se intendevi usare un valore predefinito. Dal momento che non è chiaro, è male. E quindi risultati probabili in errori.

Le scelte di progettazione di Kotlin aiutano a eliminare i bug dovuti al codice in cui il compilatore non può aiutare a determinare se c'è un errore. È filosofico e coerente nella lingua.

Kotlin richiede l'inizializzazione prima dell'uso. Per i membri che significano che i costruttori e gli inizializzatori del tempo sono completati, devono avere un valore. Il modificatore lateinit su var consente di ignorarlo in fase di compilazione anche se in fase di esecuzione il controllo viene eseguito quando si accede alla variabile. Per le variabili locali, qualsiasi ramo di codice deve inizializzare il valore prima dell'accesso. Per esempio:

fun stateFromAbbreviation(abbreviation: String?): String { 
    val state: String 

    if (abbreviation == null) { 
     state = DEFAULT_STATE 
    } 
    else { 
     state = stateMap.get(abbreviation) ?: throw IllegalStateException("Invalid state abbreviation $abbreviation") 
    } 

    return state 
} 

Qui la variabile locale può essere inizializzato nel if dichiarazione assumendo tutti i rami inizializzare il valore. Ma in realtà, questo codice sarebbe più idiomatica utilizzando il if come espressione, come ad esempio:

fun stateFromAbbreviation(abbreviation: String?): String { 
    return if (abbreviation == null) { 
     DEFAULT_STATE 
    } 
    else { 
     stateMap.get(abbreviation) ?: throw IllegalStateException("Invalid state abbreviation $abbreviation") 
    } 
} 
Problemi correlati