web-dev-qa-db-fra.com

Swift: implémenter une variable de protocole comme un var paresseux?

Il semble qu'il ne soit pas possible d'implémenter une variable requise par un protocole, avec une variable paresseuse. Par exemple:

protocol Foo {
  var foo: String { get }
}

struct Bar: Foo {
  lazy var foo: String = "Hello World"
}

Le compilateur se plaint que Type 'Bar' does not conform to protocol 'Foo'.

Il n'est pas non plus possible d'ajouter le mot clé lazy dans la déclaration de protocole, car vous obtenez alors 'lazy' isn't allowed on a protocol requirement Erreur.

Ce n'est donc pas du tout possible?

22
Kevin Renskers

Citation le Guide du langage - Propriétés - Propriétés stockées paresseuses [ accentuation mine]:

Une propriété stockée paresseuse est une propriété dont la valeur initiale n'est calculée que la première fois qu'elle est utilisée .

C'est-à-dire que la valeur est mutée lors de la première utilisation. Puisque foo a été tracé dans le protocole Foo en tant que get, implicitement nonmutating get, le type de valeur Bar ne remplit pas cette promesse avec sa propriété lazyfoo, une propriété avec un getter mutating.

Changer Bar en un type de référence lui permettra de remplir le plan Foo (car la mutation d'une propriété d'un type de référence ne mute pas l'instance de type elle-même):

protocol Foo {
    var foo: String { get }
}

class Bar: Foo {
    lazy var foo: String = "Hello World"
}

Alternativement, spécifiez dans le plan de la propriété foo de Foo qu'elle a un getter mutating.

protocol Foo {
    var foo: String { mutating get }
}

struct Bar: Foo {
    lazy var foo: String = "Hello World"
}

Voir les questions et réponses suivantes pour plus de détails sur les spécificateurs mutating/nonmutating pour les getters et les setters:

26
dfri