2015-04-19 17 views
5

La classe A fornisce un valore stringa. La classe B ha due membri di tipo A dentro se stessa e fornisce una proprietà calcolata "v" per sceglierne uno.Swift: impossibile assegnare un valore a una proprietà del protocollo?

class A { 
    var value: String 

    init(value: String) { 
     self.value = value 
    } 
} 

class B { 
    var v1: A? 
    var v2: A = A(value: "2") 

    private var v: A { 
     return v1 ?? v2 
    } 

    var value: String { 
     get { 
      return v.value 
     } 
     set { 
      v.value = newValue 
     } 
    } 
} 

Questo codice è semplice e funziona. Dal momento che entrambi i terminali A e B hanno un "valore" membro, mi fanno un protocollo come questo:

protocol ValueProvider { 
    var value: String {get set} 
} 

class A: ValueProvider { 
    var value: String 

    init(value: String) { 
     self.value = value 
    } 
} 

class B: ValueProvider { 
    var v1: ValueProvider? 
    var v2: ValueProvider = A(value: "2") 

    private var v: ValueProvider { 
     return v1 ?? v2 
    } 

    var value: String { 
     get { 
      return v.value 
     } 
     set { 
      v.value = newValue // Error: Cannot assign to the result of the expression 
     } 
    } 
} 

Se cambio il seguente codice

v.value = newValue 

a

var v = self.v 
v.value = newValue 

E ' funziona di nuovo!

Si tratta di un bug di Swift o qualcosa di speciale per la proprietà dei protocolli?

risposta

10

è necessario definire il protocollo come un class protocollo:

protocol ValueProvider : class { 
    var value: String {get set} 
} 

Poi

var value: String { 
    get { return v.value } 
    set { v.value = newValue } 
} 

compila e funziona come previsto (cioè assegna il nuovo valore all'oggetto fa riferimento v1 se v1 != nil e all'oggetto riferito a v2 in caso contrario.

v è una proprietà di sola lettura del tipo ValueProvider. Definendo il protocollo come protocollo classe il compilatore sa che v è un tipo riferimento, e quindi la sua struttura v.value possono essere modificati anche se il riferimento stesso è una costante.

L'esempio di codice iniziale funziona perché la proprietà v ha il tipo A che è un tipo di riferimento.

E la vostra soluzione alternativa

set { 
    var tmp = v1 ?? v2 
    tmp.value = newValue 
} 

opere, perché le proprietà di variabili (lettura-scrittura) può essere impostato in ogni caso (tipo di valore o tipo di riferimento).

+0

Bella risposta e grazie. –