2016-01-16 3 views
0

Pour autant que je sache, Swift nous permet de définir des observateurs de propriétés pour les propriétés stockées et calculées. Mais si la valeur de la propriété calculée dépend d'un magasin de soutien, les observateurs de propriété ne sont pas déclenchés lorsque ces valeurs de magasin de support sont changées:Swift: les observateurs de propriétés pour les propriétés calculées

public class BaseClass { 
    private var privateVar1: Int = 0 
    private var privateVar2: Int = 0 
    public var property: Int { 
     get { 
      return privateVar1 * privateVar2 
     } 
     set { 
      print("some setter without effect") 
     } 
    } 
    private func changeSomeValues() { 
     privateVar1 = 1 
     privateVar2 = 2 
    } 
} 

public class SubClass : BaseClass { 
    override var property: Int { 
     didSet { 
      print("didSet \(property)") 
     } 
    } 
} 

didSet de SubClass n'est pas appelée lorsque changeSomeValues ​​est appelé.

Considérons un cas: nous avons une telle BaseClass dans une structure tierce. Nous définissons SubClass dans notre application. La question est: comment pouvons-nous compter sur des observateurs SubClass sans connaissance de la nature de la propriété: est-elle stockée (et nous pouvons compter sur des observateurs) ou calculée (et nous ne pouvons pas attendre des observateurs de tir chaque fois que nous l'attendons)? C'est possible? Si non, est-ce une violation d'incapsulation?

+0

Votre code n'est pas valide et ne compile pas. 'property' est en lecture seule. Si 'property' est une propriété calculée en lecture-écriture, alors' didSet' se déclenchera sur la sous-classe, comme prévu. – Darren

Répondre

0

Ce comportement est parfaitement normal. Le compilateur n'a aucun moyen de savoir quel magasin de sauvegarde correspond réellement à quelle propriété calculée. Votre magasin de support dans ce cas est constitué de variables privées qui ne seront pas accessibles en dehors de la classe elle-même. Donc, le seul endroit où un changement «sous le capot» peut se produire est dans la classe de base. C'est la prérogative de cette classe d'utiliser ses propriétés calculées (qui déclencheront les observateurs) ou le backstore (ce qui ne sera pas le cas). Dans votre exemple, en supposant que vous ne souhaitiez jamais autoriser les modifications "invisibles", la fonction changeSomeValues ​​() rompt ses propres règles et ne respecte pas le contrat qu'elle a promis à ses sous-classes et ses appelants.

+0

Par exemple, ma classe de base est 'UView' et une propriété est' frame'. Personne ne sait s'il s'agit d'une propriété calculée ou stockée car il s'agit d'un détail d'implémentation. La question est: est-ce que je peux compter sur le tir de didSet pour chaque changement de 'frame' chaque fois que j'attends? Si oui, comment est-ce garanti et mis en œuvre? Si non, cela rend-il inutile le concept d'observateur de biens? – slashdot

+0

Apple n'a pas garanti l'observation de la propriété frame. Si vous voulez ajouter cela au contrat, vous êtes peut-être lié. Je n'ai pas lu la documentation en détail, mais je crois que le cadre est simplement un concept de commodité pour accéder à bounds & center qui sont le concept de base qui sont vraiment au cœur du design d'UIView. Dans tous les cas, la documentation d'Apple suggère d'utiliser KVO pour toutes les propriétés de la vue, ce que je n'aime pas. https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CocoaViewsGuide/SubclassingNSView/SubclassingNSView.html –

+0

Vous devez également garder à l'esprit que Swift n'a pas existé depuis si longtemps. Objective-C a été le roi de la colline pour l'année et la conception de cadres iOS/OSX a été fortement entachée par les idiosyncrasies et les limitations des constructions de langage plus anciennes et l'évolution progressive. Si iOS avait été créé à l'aide de Swift, les API et les conceptions de classes exploiteraient beaucoup plus de fonctionnalités de Swift. Les bonnes nouvelles sont que Apple fait exactement cela exactement. Par exemple, l'abandon des valeurs de retour de NSError vers les blocs do/catch. –