2015-08-23 9 views
13
class Animal { 
    class func generate() -> Animal { 
     return self() 
    } 
} 

Il compilatore si lamenta costruire un oggetto di tipo di classe 'Animal' con un valore metatipo deve utilizzare un inizializzatore 'necessaria'Perché la costruzione di un oggetto di tipo classe "someClass" con un valore metatype utilizza un inizializzatore "richiesto"?

posso capire questo. Se scrivo una sottoclasse come questo:

class SubAnimal: Animal { 
    let head: Int 
    init(head: Int) { 
     self.head = head 
     super.init() 
    } 
} 

esso erediterà metodo di classe Animal s' generate() ma non erediterà la sua inizializzazione di default init(). Quindi SmallAnimal.generate() chiama effettivamente SmallAnimal(), ma SmallAnimal non ha un inizializzatore init()! Ovviamente questo è ciò che il compilatore vuole impedire.

Ciò che mi confonde è un problema simile.

class someClass { 

} 
let anotherClass = someClass.self 
let anotherObject = anotherClass() 

Il compilatore segnala ancora costruire un oggetto del tipo classe 'animale' con un valore metatipo deve utilizzare un inizializzatore 'richiesto'.

Questa volta, non riesco a capire. anotherClass è un valore di metatype , ma quale cattivo risultato verrà causato?

So come risolvere questo problema, aggiungendo required init() {} è la soluzione. Ma voglio davvero sapere la ragione del secondo caso.

risposta

11

Si consideri il caso in cui abbiamo anche una sottoclasse:

class SomeClass { 

} 

class SomeSubclass : SomeClass { 

} 

Se si memorizza il tipo di classe in una variabile:

var anotherClass = SomeClass.self 

La variabile anotherClass è di tipo SomeClass.Type.

È possibile in seguito assegnare questa variabile per una sottoclasse:

anotherClass = SomeSubclass.self 

Questo è valido perché è un SomeSubclass.TypeSomeClass.Type. A questo punto, anotherClass() non funzionerà se l'inizializzatore non è implementato nella sottoclasse. Questo è ciò contro cui il compilatore sta proteggendo.

Nel codice di esempio, questo è impossibile: è stato utilizzato let anziché var, pertanto la modifica del tipo è impossibile. Può darsi che i controlli di sicurezza non siano abbastanza sfumati per notarlo.

+0

Ottima risposta. Forse 'let anotherClass: SomeClass.Type = SomeSubClass.self' è più conciso? – fujianjin6471

+0

Il tipo 'anotherClass' è' SomeClass.Type', quindi usiamo l'inizializzatore di 'SomeClass'. Ma è davvero un 'SomeSubClass', e' SomeSubClass' potrebbe non ereditare l'inizializzatore di 'SomeClass'. Ecco come viene fuori il cattivo risultato. – fujianjin6471

Problemi correlati