2014-10-06 17 views
8

Si consideri il seguente parco giochi:Swift Protocollo di eredità e generiche funzioni

import Foundation 

protocol StringInitable { 
    init(string:String) 
} 

class A : StringInitable { 
    var stored:String 

    required init (string:String) { 
     stored = string 
    } 
} 

class B : A /*, StringInitable */ { 
    var another_stored:String 

    required init (string:String) { 
     another_stored = "B-store" 

     super.init(string: string) 
    } 
} 

func maker<T:StringInitable>(string:String) -> T { 
    return T(string: string) 
} 

let instanceA = A(string: "test-maker-A") 
let instanceB = B(string: "test-maker-B") 

let makerA:A = maker("test-maker-A") 
let makerB:B = maker("test-maker-B") 

let typeInstanceA = _stdlib_getTypeName(instanceA) 
let typeMakerA = _stdlib_getTypeName(makerA) 

let typeInstanceB = _stdlib_getTypeName(instanceB) 
let typeMakerB = _stdlib_getTypeName(makerB) 

Dai risultati del compilatore sembra aver dedotto i tipi corretti, ma non è riuscita a chiamare i inizializzatori corretti. Come mai devo implementare in modo esplicito StringInitable nella classe B (test rimuovendo il commento nella definizione della classe B) per fare in modo che la funzione generica "maker" chiami l'inizializzatore corretto?

+0

Ha funzionato per me una volta aggiunto l'identificatore "richiesto" davanti alla funzione init. – user965972

risposta

2

Che suona come un errore del compilatore per una semplice ragione: makerB è una variabile del tipo B, ma a questa viene assegnata un'istanza di A. Questo non dovrebbe essere possibile, e infatti se provate a stampare, e più in generale ad accedere alla proprietà another_stored della variabile makerB, viene sollevata un'eccezione di runtime e non mi aspettoi altro.

Questo perché se B è una sottoclasse di A, un'istanza di A non può essere assegnato ad una variabile di tipo B (che è possibile l'opposto).

Assegnazione di una variabile di A tipo di una variabile di B tipo è possibile, anche se, ma solo a queste condizioni:

  • un abbattuto esplicito A-B è fatto (il compilatore dovrebbe errore altrimenti)
  • l'istanza riferisce la variabile A tratta di un'istanza di B (un'eccezione runtime dovrebbe essere sollevata altrimenti)

Si noti che il compilatore non ha mancato di chiamare l'inizializzatore corretto - ha chiamato l'inizializzatore di un'altra classe

Problemi correlati