web-dev-qa-db-fra.com

Swift vs propriétés calculées

Disons que j'ai une classe Event comme suit:

class Event {
    private var attendees: [Person] = []

    // Case 1
    //*******
    // Should I use a func…
    func countOfAttendees() -> Int {
        return attendees.count
    }

    // …or a var
    var countOfAttendees: Int {
        return attendees.count
    }

    // Case 2
    //*******
    // Should I use a func…
    func countOfPaidAttendees() -> Int {
        return attendees.filter({$0.hasPaid}).count
    }

    // …or a var
    var countOfPaidAttendees: Int {
        return attendees.filter({$0.hasPaid}).count
    }
}

Est-il recommandé d'utiliser fonctions ou propriétés calculées dans les 2 cas indiqués ci-dessus?

28
Ashley Mills

Suivez le niform Access Principle ,

Tous les services offerts par un module doivent être disponibles via une notation uniforme, qui ne trahit pas s'ils sont implémentés par le stockage ou par le calcul

Pour moi, cela signifie que je n'écris pas de fonctions qui ne prennent aucun argument et renvoient une valeur. J'utilise toujours des propriétés calculées. De cette façon, si je décide par la suite de changer la propriété calculée en une propriété stockée, je peux le faire sans avoir envie de supprimer les parens partout dans mon application et sans avoir une méthode "getter" distincte qui renvoie simplement la valeur d'une propriété stockée propriété, ce qui semble IMHO assez gaspillage.

Et si je change une propriété stockée en une propriété calculée, je n'ai pas besoin d'ajouter de parens à la fin de celle-ci, et partout où elle est utilisée dans l'application.

16
Daniel T.

Je dirais que cela dépend de la complexité du calcul par rapport à la fréquence d'utilisation.

  • Si c'est O(1)/*, Alors utilisez la propriété calculée.
  • Si c'est O(N)+/rare-use, Alors utilisez la fonction.
  • Si c'est O(N)+/frequent-use, Pensez si à l'avenir vous pourriez décider d'utiliser la mise en cache ou d'autres techniques "intelligentes" pour compenser la complexité, si "oui" alors utilisez la propriété, si " non-non-non, c'est juste lourd "puis utilisez la fonction.
18
courteouselk

J'ai récemment commencé à apprendre Kotlin et ils ont une excellente heuristique sur le moment d'utiliser les propriétés calculées:

Fonctions vs propriétés

Dans certains cas, les fonctions sans argument peuvent être interchangeables avec des propriétés en lecture seule. Bien que la sémantique soit similaire, il existe certaines conventions stylistiques sur le moment de préférer l'une à l'autre.

Préférez une propriété à une fonction lorsque l'algorithme sous-jacent:

  • ne jette pas
  • a une complexité O(1)
  • est bon marché à calculer (ou a pu être effectué lors de la première exécution)
  • renvoie le même résultat lors des invocations

- https://kotlinlang.org/docs/reference/coding-conventions.html

10
Daniel T.

Dans Swift, les fonctions sans paramètres et propriétés calculées ont presque les mêmes capacités (il peut y avoir une différence qu'une fonction sans paramètre est également une fermeture, alors qu'une propriété calculée ne l'est pas).

La différence est sémantique. Si votre code effectue une action et retourne par exemple une description du résultat de cette action, alors j'utiliserais une fonction. Si votre code calcule une propriété mais du point de vue de l'utilisateur, cela aurait pu être une propriété stockée, ou peut-être une propriété stockée qui nécessite d'abord la mise à jour d'une valeur mise en cache, alors j'utiliserais une propriété calculée.

Une grande différence: que se passe-t-il si vous appelez deux fois la fonction ou la propriété calculée? Pour une propriété calculée, je m'attends à ce que x = propriété; la propriété y = a exactement le même comportement que la propriété x =; y = x sauf qu'il peut fonctionner un peu plus lentement. Pour les fonctions, je ne serais pas surpris si le comportement était différent.

7
gnasher729

Utilisez countOfAttendees et countOfPaidAttendees().


Une variable calculée est une variable qui renvoie une valeur calculée à chaque fois qu'elle est accédée. Autrement dit, il ne stocke pas de valeur. En interne, il est implémenté en fonction.

Quelle est la différence avec une fonction?

  • Sémantiquement, une variable est un état, une fonction est une action.
  • Une fonction régule l'accès au stockage privé. Une variable calculée peut faire de même de manière plus compacte. Exemple .
  • Une variable calculée peut être utilisée avec KVO, transmise sous la forme d'un #keypath et possède des fonctions d'observation: willSet, didSet.

Vous devez utiliser une variable lorsque

  • ça ne jette pas
  • il renvoie une propriété simple
  • il n'a pas d'effet secondaire ni de verbe dans son nom
  • c'est O (1), c'est-à-dire qu'il n'entraîne pas de coût important. Dans votre exemple, ce sera O (n).
  • c'est idempotent. Plusieurs invocations identiques renvoient la même valeur ou définissent l'objet au même état.

Raisons non pertinentes de préférer une variable à une fonction

  • Une variable calculée vous évite de taper (). Cependant, la clarté est plus importante que la brièveté, c'est donc un argument faible.
  • Une variable en lecture seule peut être remplacée en lecture/écriture. Une fonction indique qu'elle est toujours en lecture seule. Cependant, Apple utilise des propriétés pour les variables en lecture seule comme array.count. En cas de doute, recherchez la cohérence avec la plate-forme.

Ressources

De WWDC 2014 - 204 Quoi de neuf dans Cocoa > 24:40 Quand utiliser un @property

Utilisez la propriété pour tout ce qui concerne la valeur ou l'état d'un objet ou sa relation avec d'autres objets. Mauvais candidats:

  • Méthodes qui font les choses: charger, analyser, basculer,…. Ils ont des verbes en son nom.
  • Générateurs: init, copy, énuméré,…. Ces méthodes ne sont pas idempotentes.
  • Méthodes qui changent d'état: nextObject.

De Swift Style par Erica Sadun > Propriétés calculées vs méthodes

Une propriété exprime la qualité inhérente d'une instance, tandis qu'une méthode effectue une action.

  • Les méthodes ont des paramètres; les propriétés ne le font pas. Préférez les méthodes pour tout appel avec effets secondaires. Si une méthode fait quelque chose (par exemple, elle charge, analyse, bascule ou imprime) ou a un nom de verbe, elle ne doit pas être une propriété.
  • Préférez les propriétés des valeurs simples que vous pouvez obtenir et/ou définir.
  • Les propriétés doivent exprimer une qualité intrinsèque sémantique d'une instance de type.
  • Les propriétés vous permettent d'ajouter des observateurs via willSet et didSet. Contrairement aux propriétés d'instance stockées, les propriétés de type stockées doivent toujours recevoir une valeur par défaut.

De Conventions de codage Kotlin> fonctions vs propriétés . Voir réponse de Daniel ci-dessus .

Autres ressources sans informations pertinentes:

5
Jano

J'utiliserais un func. La programmation orientée objet fonctionne très bien sans propriétés calculées. Parce que vous récupérez une valeur qui a été calculée/filtrée, certains peuvent affirmer qu'une propriété calculée se sent bien. Mais voici ma plainte, si vous faites cela, alors la lisibilité prend un coup, car cela ressemble à une valeur.

Dans ce contexte, cela n'aurait aucun sens d'essayer d'attribuer la valeur calculée (et heureusement, le IDE nous aide à éviter cela), mais que se passe-t-il si j'essaie d'affecter quelque chose qui est calculé mais qui ressemble à un valeur?

event.countOfAttendees = 0; // not possible

Lorsque vous utilisez func, l'appelant sait que vous ne traitez pas directement avec une valeur:

event.countOfAttendees()

Je pense que si c'est un objet comportemental, il devrait ressembler à un comportement plutôt qu'à une structure de données. Si votre objet est stupide et n'a aucun comportement, alors pourquoi essayer de l'encapsuler? Dans ce cas, vous pourriez tout aussi bien que les participants soient publics

3
morbidhawk