2014-11-01 23 views
52

ho notato che il compilatore non mi permette di sostituire una proprietà memorizzati con un altro valore memorizzato (che sembra strano):Override di una proprietà memorizzato in Swift

class Jedi { 
    var lightSaberColor = "Blue" 
} 


class Sith: Jedi { 
    override var lightSaberColor = "Red" // Cannot override with a stored property lightSaberColor 
} 

Tuttavia, mi è permesso di fare questo con una proprietà calcolata:

class Jedi { 
    let lightSaberColor = "Blue" 
} 


class Sith: Jedi { 
    override var lightSaberColor : String{return "Red"} 

} 

Perché non è possibile dargli un altro valore?

Perché sovrascrivere una proprietà memorizzata è un abominio e farlo con un kosher calcolato? Che cosa stanno pensando?

+0

possibile duplicato del [Override proprietà superclasse con diverso tipo a Swift] (http://stackoverflow.com/questions/24094158/overriding-superclass-property-with-different-type-in-swift) –

risposta

34

Perché non mi è consentito dargli un altro valore?

È possibile assegnare una proprietà ereditata a un valore diverso. È possibile farlo se si inizializza la proprietà in un costruttore che accetta che il valore iniziale, e passa un valore diverso dalla classe derivata:

class Jedi { 
    // I made lightSaberColor read-only; you can make it writable if you prefer. 
    let lightSaberColor : String 
    init(_ lsc : String = "Blue") { 
     lightSaberColor = lsc; 
    } 
} 

class Sith : Jedi { 
    init() { 
     super.init("Red") 
    } 
} 

let j1 = Jedi() 
let j2 = Sith() 

println(j1.lightSaberColor) 
println(j2.lightSaberColor) 

Override di una proprietà non è lo stesso di dare un nuovo valore - è è più come dare a una classe una proprietà diversa. In effetti, questo è ciò che accade quando si esegue l'override di una proprietà calcolata: il codice che calcola la proprietà nella classe base viene sostituito dal codice che calcola l'override per quella proprietà nella classe derivata.

[È possibile sovrascrivere la proprietà archiviata effettiva, ovvero lightSaberColor che ha qualche altro comportamento?

A parte gli osservatori, le proprietà memorizzate non hanno un comportamento, quindi non c'è davvero nulla da escludere. Dando alla proprietà un valore diverso è possibile attraverso il meccanismo sopra descritto. Questo fa esattamente ciò che l'esempio nella domanda sta cercando di ottenere, con una sintassi diversa.

+2

@MaxMacLeod Oltre agli osservatori, le proprietà memorizzate non hanno un comportamento, quindi non c'è davvero nulla da escludere. Voleva dare a una proprietà immagazzinata un valore diverso nella sottoclasse, ma non era sicuro del meccanismo per raggiungerlo. La risposta spiega come può essere fatto in Swift. Mi dispiace per la risposta tardiva, sembra che il tuo commento causi abbastanza confusione per attirare downvotes, quindi ho deciso di spiegare cosa sta succedendo. – dasblinkenlight

10

probabilmente avrete bisogno di assing un altro valore alla proprietà:

class Jedi { 
    var lightSaberColor = "Blue" 
} 


class Sith: Jedi { 
    override init() { 
     super.init() 
     self.lightSaberColor = "Red" 
    } 
} 
+7

vale come per il commento sopra –

17

Per me il tuo esempio non funziona a Swift 3.0.1.

Inserito nel parco giochi di questo codice:

class Jedi { 
    let lightsaberColor = "Blue" 
} 

class Sith: Jedi { 
    override var lightsaberColor : String{return "Red"} 
} 

genera un errore in fase di compilazione in Xcode:

non può ignorare immutabile 'lasciare' proprietà 'lightsaberColor' con il getter di un 'var'

No, non è possibile modificare il tipo di una proprietà memorizzata. Il Principio di sostituzione di Liskov obbliga a consentire l'utilizzo di una sottoclasse in un luogo in cui si desidera la superclasse.

Ma se lo si cambia in var e quindi si aggiunge set nella proprietà conteggiata, è possibile sovrascrivere la proprietà memorizzata con una proprietà conteggiata dello stesso tipo.

class Jedi { 
    var lightsaberColor = "Blue" 
} 


class Sith: Jedi { 
    override var lightsaberColor : String { 
     get { 
      return "Red" 
     } 
     set { 
      // nothing, because only red is allowed 
     } 
    } 
} 

Ciò è possibile perché può avere senso passare dalla proprietà archiviata alla proprietà calcolata.

Ma ignorare una proprietà var memorizzata con una proprietà var memorizzata non ha senso, perché è possibile solo modificare il valore della proprietà.

Tuttavia, non è possibile sovrascrivere una proprietà memorizzata con una proprietà memorizzata.


Non direi Sith sono :-P Jedi. Pertanto è chiaro che questo non può funzionare.

3
class SomeClass { 
    var hello = "hello" 
} 
class ChildClass: SomeClass { 
    override var hello: String { 
     set { 
      super.hello = newValue 
     } 
     get { 
      return super.hello 
     }  
    } 
} 
+5

Anche se questo snippet di codice può risolvere la domanda, [compresa una spiegazione] (http://meta.stackexchange.com/questions/114762/explaining-entually-code-based-answers) aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro, e queste persone potrebbero non conoscere le ragioni del tuo suggerimento sul codice. – DimaSan

4

Per Swift 4, da Apple's documentation:

È possibile ignorare un'istanza ereditato o tipo di proprietà per fornire il proprio getter personalizzato e setter per la proprietà, o per aggiungere osservatori proprietà a abilitare la proprietà che sovrascrive per osservare quando cambia il valore della proprietà sottostante.

Problemi correlati