Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift property override not working

Tags:

When I try to override a property I get an error "can not override mutable property with read-only property"

I have provided get and set in the super class.

class Card {     var contents:String {         get {             return self.contents         }         set {             self.contents = newValue         }     }     init() {         self.contents = ""     } } 

Here is my Subclass where I am trying to override the "contents" property.

class PlayingCard: Card {     override var contents:String { //<-- this is where I get the build error         get {             var rankStrings:Array<String> = PlayingCard.rankStrings()             return rankStrings[Int(self.rank)] + self.suit         }     } } 

What exactly am I doing wrong?

like image 287
DerrickHo328 Avatar asked Sep 30 '14 03:09

DerrickHo328


People also ask

Can we override stored property in Swift?

Hi, Swift rules state that any inherited property can be overridden whether it is implemented as a stored or computed property at source (parent class).

How does override work in Swift?

In Swift Inheritance, the subclass inherits the methods and properties of the superclass. This allows subclasses to directly access the superclass members. Now, if the same method is defined in both the superclass and the subclass, then the method of the subclass class overrides the method of the superclass.


1 Answers

If the property you're overriding has both a getter and a setter, you need to provide both in your subclass as well. Here's the relevant part from the Swift language guide (emphasis mine):

You can present an inherited read-only property as a read-write property by providing both a getter and a setter in your subclass property override. You cannot, however, present an inherited read-write property as a read-only property.

If you're not doing anything special with the value, then you'll typically want to pass the value being set on to the base class:

set {     super.contents = newValue } 

You could also just discard the value with an empty setter (although I can't think of a good reason to do this offhand):

set { } 

I also wanted to point out that you have an infinite loop in the contents property in your Card class. When you you do this:

get {     return self.contents } 

You're actually just calling that same getter again, creating an infinite loop; you're doing the same with the setter. Swift doesn't create ivars for your properties automatically like Objective-C did, so you need to create them yourself. A more appropriate way to create that property would be to do something like this:

class Card {     private var _contents: String     var contents: String {         get {             return _contents         }         set {             _contents = newValue         }     }     init() {         _contents = ""     } } 

However, since you're not doing anything other than setting and returning _contents in your setter and getter, you can simplify it down to this:

class Card {     var contents: String = ""     init() {      } } 

Note: contents might also be a good candidate for using an optional (String?) and setting it to nil rather than initializing it to an empty string.

like image 174
Mike S Avatar answered Oct 02 '22 19:10

Mike S