8
votes

Convention de dénomination Scala pour "Setteurs" sur des objets immuables

Je ne sais pas quoi appeler mes "setters" sur des objets immuables?

Pour une personne d'objet mutable, les Setters fonctionnent comme ceci: xxx

c'est tout Eh bien et bien, mais si la personne est immuable? xxx

Que doit whaherename être appelé?

edit : J'ai besoin de mettre des choses dans la méthode "Setter", comme ceci: xxx

Le code réel est beaucoup plus grand que cela, donc un appel simple à la copie < / code> méthode ne fera pas.

EDIT 2:

Comme il y a tellement de commentaires sur mon exemple funéré (qu'il est incorrect) je ferais mieux Donnez-vous le lien à la classe réelle ( avatar ).

Les méthodes "Setter" Je ne sais pas quoi d'appeler sont updatetrongengength , updatewisdom ... Mais je vais probablement changer cela en avec longueur bientôt ..


7 Réponses :


13
votes

J'aime la voie Jodatime. Ce serait avec nom.

val p = new Person("Olle")
val p2 = p.withName("kalle");


1 commentaires

Chose cool. C'est juste que "avec" me fait penser au mot clé utilisé pour la mixine.



10
votes

Les classes de cas Scala ont une méthode autogogéné Copier à cet effet. C'est utilisé comme ça: xxx


2 commentaires

La méthode "Setter" devrait probablement utiliser la méthode de la copie en interne. Mais la méthode "Setter" peut faire plus que simplement définir la valeur, elle pourrait inclure la logique qui valide le nouveau nom.


Vous avez demandé à propos de la Convention, la méthode largement utilisée existante est donc un bon exemple de la façon dont cela peut être fait. Vous pouvez écrire votre propre méthode de copie avec votre propre validation et vous semblera familier à ceux qui utilisent des classes de cas.



2
votes

Ajout à Oleg Répondre, vous écririez la classe comme celle-ci:

case class Person(name: String, age: Int, email: EMail, pets: List[Pet] = List())
val joe = Person("Joe", 41, EMail("joe@example.com"))
val joeAfterHisNextBirthday = joe.copy(age=42)


1 commentaires

Merci @soc, mais ce n'est pas vraiment ce que je cherche. Mon exemple ci-dessus est une version très simplifiée du vrai problème. Dans mon exemple réel, j'ai besoin d'une méthode "Setter", qui enveloppe la méthode de la copie. Et la question est: que devrait-elle être appelée?



1
votes

comme pour l'instant, j'utilise maintenant update convention de nom pour tous les méthodes "Setter" à des objets immuables.

Je ne peux pas utiliser définir puisqu'il rappelle trop des sets mutables en Java.

Comment vous sentez-vous de l'utilisation d'utiliser update pour toutes les méthodes qui renvoie une nouvelle instance de la même identité que l'instance actuelle?


3 commentaires

Cela sonne bien, bien que je préfère avec un minuscule un peu.


Si vous suivez d'autres conventions Scala (en particulier avec la bibliothèque de collections), vous devriez préférer «mise à jour» sur 'Update'. «Mise à jour» suggère toujours une opération de mutation. Avoir dit tout ça, je suis toujours favorable à "avec"


Bien alors "avec" c'est! Merci les gars.



4
votes

Si vous devez effectuer une validation, etc. Lorsque vous «modifier» un champ, pourquoi cela devrait-il être différent de la validation lorsque vous créez d'abord l'objet ?

Dans ce cas, vous pouvez ensuite mettre la logique de validation / erreur d'erreur nécessaire dans le constructeur d'une classe de cas, ce qui sera utilisé chaque fois qu'une nouvelle instance est créée via la méthode copie .


8 commentaires

Vous êtes correct @kevin, mais l'exemple ci-dessus n'est pas du tout ce que mon vrai code ressemble (désolé à ce sujet). Dans mon code, toutes les "Setters" ne font pas validation, ils appellent une méthode d'utilité commune qui prend soin de la création d'instance. Dans mon code, je ne peux pas utiliser de copie car je dois mélanger des traits.


@Kevin j'ai mis à jour la question avec un lien vers le code réel. C'est un objet immuable complexe. Je vous ai le temps de jeter un coup d'oeil, je serais heureux.


Ces mixines vont simplement vous causer plus de douleur au fil du temps. Vous devriez absolument favoriser la composition au lieu d'héritage ici; Votre code semble dire qu'un avatar est-un métier et une course, c'est faux, un avatar a-à-faire une profession et une course. Encodez les concepts fondamentaux correctement et tout le reste devrait alors tomber en place beaucoup plus facilement et naturellement.


@Kevin pour la situation d'objet mutable, il est assez agréable d'avoir l'avatar "étant" une créature (étant un nain) et "être" un professionnel (c'est-à-dire un voleur), voir bit.ly/bwdo1b . La raison pour laquelle Java favorise la composition de ce cas est imho l'absence de multiples héritage. Pour la situation de l'objet immuable, cela est, comme vous le dites, pas très facile à faire avec des traits de Scala. Donc, la solution basée sur la composition semble tentante. Ou? Faites-moi savoir si vous refusez la solution mutable aussi ..


L'idée de base ne vient pas simplement de l'absence d'héritage multiple (même si c'était sans doute une force de motivation), vous pouvez le voir en regardant comment le style de conception a déplacé pour favoriser la composition en C ++. La pensée actuelle est de réduire le couplage autant que possible. Cela aide avec les tests unitaires, il fonctionne également très bien avec l'immutabilité - permettant ainsi des objets immuables composés à être facilement mis à jour via quelque chose comme la méthode Copier disponible sur les classes de cas. Et oui, je vous conseillerais également de favoriser des objets immuables :)


@Kevin Je ne suis pas sûr que la composition réduira beaucoup le couplage pour mon code. Si j'utilise la composition dans mon code, l'avatar "aurait" une profession et "avoir" une course. Mais la classe de profession doit avoir une référence à Avatar pour accéder aux champs. Cette "double dépendance" est-elle encore appelée composition? Dans tous les cas, la profession ne peut pas être testée isolément.


@Kevin Plusieurs héritage ne fonctionnent pas très bien en C ++, C ++ n'a pas une bonne solution pour le problème de diamant. Scala est une bête différente, je pense donc que plusieurs héritages peuvent être utilisés (si cela ressent le "droit" pour le problème réel). Mon objectif pour l'exemple que je travaille est d'explorer comment fonctionne de multiples héritage dans Scala.


D'après ce que je peux voir, tout le couplage est via la force / le charisme / etc. Pourquoi ne pas tirer ces qualités dans une classe dédiée (immuable) de la classe qui peut être transmise et hors fonction des fonctions.



3
votes

Vous pouvez définir une seule méthode pour cela. Copier ou, au cas où il est déjà une classe de cas, avec : xxx

edit < / p>

La méthode copie sur l'exemple lié doit ressembler à ceci: xxx


2 commentaires

J'ai mis à jour la question avec un lien vers le code réel. C'est un objet immuable complexe.


Merci de m'aider. Je vois maintenant que la stratégie de copie fonctionne pour mon code.



0
votes

Bien que les réponses précédentes résolvent le problème, je voudrais partager la manière dont je traite avec des objets immuables (ce qui n'est que du sucre syntaxique).

Pour avoir une syntaxe plus claire (IMHO), je implémente le appliquer code > Méthode dans des classes immuables, renvoyant le résultat de la méthode code> Copie Copie> dans les classes de cas et une nouvelle instance lorsqu'il s'agit d'une classe normale. IE: P>

import java.util.Date

class Tournament (val name: String, val start: Date) {
  /* With case class
  def apply (name: String = this.name, start: Date = this.start) =
    copy (name, start)
  */

  def apply (name: String = this.name, start: Date = this.start) =
    new Tournament (name, start)

  override def toString () = s"${name} at ${start}"
}

object Main extends App {
  val tour = new Tournament ("Euroleague", new Date)
  val tour2 = tour (name = tour.name + " 2014")
  println (tour)
  println (tour2)
}


0 commentaires