2014-11-24 20 views
5

La guida di Apple Swift Programming Language menziona l'esistenza dell'iniz! inizializzatore, ma non fornisce alcun esempio per questo. (Ricerca per init!)Qual è lo scopo dell'iniz! inizializzatore disponibile?

Ho compreso l'utilizzo di un inizializzatore normale disponibile dichiarato con init ?, ma non riesco a ottenere la necessità di questa altra versione. Di cosa è necessario? Qualcuno può fornire un esempio?

risposta

-3

L'inizializzatore di init è lo stesso del costruttore per le classi in altre lingue. Imposta i valori iniziali ed esegue alcune operazioni iniziali (come controllare se un valore è troppo grande ecc.). Interessante: accetta anche i parametri e può essere sovraccaricato.

Esempio:

struct Celsius { 
    var temperatureInCelsius: Double 
    init(fromFahrenheit fahrenheit: Double) { 
     temperatureInCelsius = (fahrenheit - 32.0)/1.8 
    } 
    init(fromKelvin kelvin: Double) { 
     temperatureInCelsius = kelvin - 273.15 
    } 
} 
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0) 
let freezingPointOfWater = Celsius(fromKelvin: 273.15) 

Così, quando quando si chiama lo struct restituisce valori diversi a seconda delle parametri di chiamata.

Per maggiori informazioni: http://www.informit.com/articles/article.aspx?p=2246797

+1

L'OP non chiedeva informazioni sugli inizializzatori in Swift in generale, ma sullo specifico inizializzatore 'init!' Failable –

1

Questo serve a due scopi:

  • Quando si importano le API Cocoa che Swift non sa nulla. Se Swift non sa se un inizializzatore può restituire o meno, lo annota con! in modo che lo sviluppatore sappia che potrebbe esserci un nascondiglio nullo lì, senza costringere lo sviluppatore a testare per zero se non ci sono davvero ragioni per farlo.

  • Per gli stessi motivi, gli opzionali implicitamente non utilizzati vengono utilizzati in altri contesti (potresti essere disposto a scambiare la sicurezza in fase di compilazione per maggiore praticità in alcuni casi).

1

I belive è assolutamente lo stesso uso di ! come in optional. init? restituirà un optional. init! restituirà un facoltativo facoltativo da scartare.

Gli optionals esplicitamente non necessari sono necessari per chiamare le API Obj-C in cui non si è certi se sia possibile restituire un optional o meno. Quindi tu usi un opzionale implicitamente da scartare e si comporta come un tipo non opzionale ma si bloccherà se viene restituito un opzionale.

Si noti che quando è stata introdotta Swift la maggior parte dei framework Obj-C ha restituito solo optionals involontariamente non pubblicati ma attualmente molti di essi restituiscono optionals o tipi non opzionali perché Apple sta passando il codice e controlla se è possibile restituire un optional o no . init! è necessario ovunque in cui Apple non abbia ancora codificato correttamente gli inizializzatori.

+0

"Ma si bloccherà se viene restituito un opzionale" ... No, non si bloccherà se per prima cosa verifica che non sia "nulla". Ti evita semplicemente di doverla scartare esplicitamente una volta che hai già verificato che non è 'nil'. – Rob

1

Buona domanda Matteo, sto cercando la risposta per la stessa domanda perché init! non ha senso (se inizia sempre un oggetto e non abbiamo bisogno di optional), ma non ho trovato alcuna risposta chiara.

penso che E'perché Apple leggere documenti finito il suo lavoro: "... proprie classi Objective-C, e le classi in strutture che non sono ancora stati controllati, inizializzatori vengono importati come init!. .. "

forse util per voi, il testo in "Interagire con Obiettivo C-API"(Apple)

  • " In Objective-C, inizializzatori tornare direttamente l'oggetto che inizializzazione. Per informare il chiamante quando l'inizializzazione è fallita, un inizializzatore Objective-C può restituire zero. In Swift, questo modello è integrato nella funzione lingua chiamata inizializzazione failable. Molti Inizializzatori C Objective nei framework di sistema iOS e OS X sono stati controllati per indicare se l'inizializzazione può avere esito negativo. Questi inizializzatori Objective-C vengono importati come init (...) - se l'inizializzazione non può fallire - o init? (...) se l'inizializzazione può fallire. Nelle proprie classi Objective-C e nelle classi che hanno non ancora verificato, gli inizializzatori vengono importati come init! (...). Per esempio , l'inizializzatore NSString (contentsOfFile :) non riesce a inizializzare un oggetto NSString se il file non esiste nel percorso fornito da . È possibile utilizzare opzionale vincolante a scartare il risultato di un inizializzatore failable se l'inizializzazione è successo ".

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html

1

ho intenzione di prendere una pugnalata a questo, anche se questa domanda è stata intorno per un po 'perché penso che un po' di codice sorgente di esempio sarebbe utile per comprendere ciò che è per init! (almeno lo è stato per me)

un implicitamente opzionale scartare fornisce due cose di valore:.

  1. una comodità per il programmatore (in modo da non dovete continuare a digitare '?' alla fine delle vostre variabili facoltative), e
  2. efficienza Runtime, perché permette di testare un optional per nil solo una volta, e successivamente (purché non sia nil) usa il suo unwrapped (es. diretto) valore.

La parte importante è però che un opzionale implicitamente scartare è ancora un optional, che significa che può essere testato per nil.

Ora, per l'utilità del init! inizializzatore -failable, siamo in grado di utilizzare per ottenere le due cose che ho elencato sopra (la convenienza e l'efficienza di esecuzione), pur consentendo una funzione init a fallire (vale a dire per tornare nil) . Ciò può accadere, come altri hanno notato, chiamando in API Objective-C, ma può anche accadere direttamente dal codice che potresti scegliere di scrivere. Ecco un esempio:

class A { 
    init!() { 
     return nil // something happens that causes init to fail 
    } 
} 

var a:A! = A()  // variable 'a' *is* an optional, and also nil 

if a != nil {  // and we can test it! 
    print("a is not nil") 
} else { 
    print("a is nil, better not use it.") 
} 

In questo esempio, mi sono dato un modo per fallire l'inizializzazione di class A, e sì, potuto facilmente essere fatto con un metodo init?, ma quando creo un oggetto di tipo A Probabilmente avrò solo bisogno di testare che l'inizializzazione sia riuscita o meno una volta - dopotutto, ho creato un A o non l'ho fatto - e poi se non è nil voglio solo usare il valore diretto. Quindi, in questo caso, l'uso dell'inizializzatore init! -file risulta molto utile.

1

Si fa la differenza in due situazioni:

Se si scrive

let x: myclass = myclass(...) 

poi init? non verrà compilato perché init? restituisce un facoltativo; dentro! si compilerà ma si bloccherà se il metodo init restituisce zero.

Se si scrive

let x = myclass(...) 

allora verrà compilato in entrambi i casi, e non andrà in crash in entrambi i casi. La differenza è che in un caso x ha digitato myclass? e nell'altro caso digita myclass! con le ovvie differenze di comportamento.

Se si scrive una delle seguenti due:

let x: myclass? = myclass(...) 
let x: myclass! = myclass(...) 

allora non importa se init! o init? è stato utilizzato, perché entrambi possono essere assegnati a un opzionale senza crash.