2016-06-30 30 views
13

Ho qualcosa che davvero mi imbarazza, in particolare il seguente codice innesca un errore del compilatore "identificatore non risolto auto", e non sono sicuro del perché questo sta accadendo, in quanto pigro significa che al momento la proprietà sarà essere usato, la classe è già istanziata. Mi sto perdendo qualcosa?Swift lanciando l'istanza usando self

Molte grazie in anticipo.

Ecco il codice

class FirstClass { 
    unowned var second: SecondClass 

    init(second:SecondClass) { 
     self.second = second 
     print("First reporting for duty") 
    } 

    func aMethod() { 
     print("First's method reporting for duty") 
    } 
} 


class SecondClass { 

    lazy var first = FirstClass(second: self) 

    func aMethod() { 
     first.aMethod() 
    } 
} 
+0

Che cosa esattamente vuoi fare? Chiama 'aMethod' da' FirstClass' nel tuo 'SecondClass'? – Dershowitz123

+0

No, basta pigramente istanziarlo, ignorare i metodi –

risposta

18

Per qualche motivo, una struttura artificiale richiede un tipo di annotazione esplicito se valore iniziale si riferisce a self. Questo è menzionato su swift-evolution mailing list, tuttavia non posso spiegare perché è necessario.

Con

lazy var first: FirstClass = FirstClass(second: self) 
//   ^^^^^^^^^^^^ 

il codice compilato ed eseguito come previsto.

Ecco un altro esempio che dimostra che il problema si verifica anche con struct s, cioè è correlato alle sottoclassi:

func foo(x: Int) -> Int { return x + 1 } 

struct MyClass { 
    let x = 1 

    lazy var y = foo(0)   // No compiler error 
    lazy var z1 = foo(self.x)  // error: use of unresolved identifier 'self' 
    lazy var z2: Int = foo(self.x) // No compiler error 
} 

Il valore iniziale di y non dipende self e non necessita di un scrivi annotazione I valori iniziali di z1/z2 dipendono da self, e vengono compilati solo con un'annotazione di tipo esplicita.

Aggiornamento: Questo has been fixed a Swift 4/Xcode 9 beta 3, inizializzatori di proprietà pigro ora possono fare riferimento i membri di istanza senza esplicito self, e senza tipo di annotazione esplicita. (Grazie a @hamish per l'aggiornamento.)

+0

W.r.t. "qualche ragione": "self" può essere di tipo "SecondClass" o un tipo di sottoclasse di "SecondClass". Ciò significa che il tipo di ritorno di un metodo di 'self' può differire in fase di esecuzione a seconda di cosa' self' è nella gerarchia di classi. Se dovessimo usare il valore di ritorno di un tale metodo di classe per istanziare pigramente 'first', allora non potremmo sapere al momento della compilazione il tipo di' first' (a causa del tipo di ritorno sovrascritto nella sottoclasse), quindi il requisito per esplicitare scrivi annotazione di 'prima'. Ora, questo non dovrebbe essere un problema quando si usa 'self' come argomento per un inizializzatore, ma probabilmente il caso sopra generalizza. – dfri

+0

(dove da "" il tipo di ritorno di qualche metodo 'self' può differire in fase di esecuzione" _ Mi riferisco al caso in cui la sottoclasse introduce un nuovo metodo con gli stessi parametri del metodo ma un tipo di ritorno diverso, fornendo una scelta di metodo ambigua in case 'self' è un oggetto sottoclasse e se la variabile lazy non doveva essere stata esplicitamente del tipo annotated.E 'strano, però, che il compilatore non possa inferire il tipo es. da un tipo di ritorno esplicito fornito quando si usa una chiusura per istanziare il pigro var, es. 'lazy var first = {() -> FirstClass in FirstClass (second: self)}()'). – dfri

+0

@dfri: Grazie per la risposta. Tuttavia, il problema sembra non essere correlato alla sottoclasse, ho aggiunto un esempio. –