web-dev-qa-db-fra.com

Swift ne fonctionne pas

Lorsque j'essaie de remplacer une propriété, j'obtiens une erreur "impossible de remplacer la propriété mutable par une propriété en lecture seule"

J'ai fourni get et set dans la super classe.

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

Voici ma sous-classe où j'essaie de remplacer la propriété "contents".

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
        }
    }
}

Qu'est-ce que je fais exactement mal?

21
DerrickHo328

Si la propriété que vous remplacez possède à la fois un getter et un setter, vous devez également fournir les deux dans votre sous-classe. Voici le partie pertinente du Swift (accent sur le mien):

Vous pouvez présenter une propriété en lecture seule héritée en tant que propriété en lecture-écriture en fournissant à la fois un getter et un setter dans votre substitution de propriété de sous-classe. Cependant, vous ne pouvez pas présenter une propriété héritée en lecture-écriture en tant que propriété en lecture seule.

Si vous ne faites rien de spécial avec la valeur, vous voudrez généralement transmettre la valeur définie à la classe de base:

set {
    super.contents = newValue
}

Vous pouvez également simplement supprimer la valeur avec un setter vide (bien que je ne puisse pas penser à une bonne raison de le faire à la main):

set { }

Je voulais également souligner que vous avez une boucle infinie dans la propriété contents dans votre classe Card. Lorsque vous faites cela:

get {
    return self.contents
}

En fait, vous appelez à nouveau ce même getter, créant une boucle infinie; vous faites de même avec le setter. Swift ne crée pas automatiquement d'ivars pour vos propriétés comme Objective-C, vous devez donc les créer vous-même. Une façon plus appropriée de créer cette propriété serait de faire quelque chose comme ceci:

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

Cependant, puisque vous ne faites rien d'autre que de définir et de renvoyer _contents dans votre setter et getter, vous pouvez le simplifier comme suit:

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

    }
}

Remarque: contents peut également être un bon candidat pour utiliser une option (String?) et en le définissant sur nil plutôt que de l'initialiser sur une chaîne vide.

31
Mike S

Le message d'erreur du compilateur est assez simple: la propriété Card de contents est mutable, c'est-à-dire qu'elle a une méthode set en plus de la get méthode.

Votre remplacement n'ajoute qu'une méthode get, vous devez également ajouter une méthode set.

Je pense que c'est ce que vous voulez:

set(newValue) {
    rankStrings[Int(self.rank)] = newValue;
}
4
Dai