Est-ce une mauvaise pratique de faire un setter retour “ce”?
Est-il une bonne ou une mauvaise idée de faire des setters de java retour "ce"?
public Employee setName(String name){
this.name = name;
return this;
}
Ce modèle peut être utile parce que vous pouvez enchaîner les setters comme ceci:
list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));
au lieu de cela:
Employee e = new Employee();
e.setName("Jack Sparrow");
...and so on...
list.add(e);
...mais ça va à l'encontre de la norme de la convention. Je suppose qu'il pourrait être utile, juste parce que cela peut faire que le setter de faire autre chose d'utile. J'ai vu ce motif est utilisé certains endroits (par exemple JMock, JPA), mais il semble rare, et seulement généralement utilisé pour définir les Api où ce modèle est utilisé partout.
Mise à jour:
Ce que j'ai décrit est évidemment valable, mais ce que je suis à la recherche de quelques réflexions sur que ce soit généralement acceptable, et s'il y a des pièges ou les meilleures pratiques. Je sais que sur le Générateur de modèle mais il est un peu plus impliqué alors ce que je viens de décrire - comme Josh Bloch décrit il y est associé à un Constructeur statique de la classe pour la création d'objet.
- Depuis que j'ai vu ce modèle il y a un moment, je le fais dans la mesure du possible. Si une méthode n'est pas explicitement besoin de retourner quelque chose à faire son travail, elle revient aujourd'hui
this
. Parfois, j'ai même de modifier la fonction de sorte qu'au lieu de retourner une valeur, il fonctionne sur un membre de l'objet, juste pour que je puisse le faire. C'est merveilleux. 🙂 - Pour télescopique setters retour auto et dans les constructeurs, je préfère utiliser avec name(String nom) au lieu de setName(String name). Comme vous l'avez souligné une pratique courante et de l'attente pour setter est de retour void. "Non standard" poseurs ne peut pas bien se comporter avec les cadres existants, par exemple les gestionnaires de l'entité JPA, Spring, etc.
- Veuillez introduire des sauts de ligne avant chaque invocation 🙂 Et configurer votre IDE ou obtenir un bon un, si ce n'est pas le respect de cette.
- Largement utilisé frameworks (Spring et Hibernate par exemple) de manière stricte (au moins ils ont utilisé pour) adhérer à void-setters convention
- Voir aussi stackoverflow.com/questions/5741369/...
Vous devez vous connecter pour publier un commentaire.
Je ne pense pas qu'il y a de quoi que ce soit incorrect avec elle, c'est juste une question de style. C'est utile lorsque:
Des Alternatives à cette méthode pourrait être:
Si vous allez seulement à définir quelques propriétés en même temps je dirais que c'est pas la peine de revenir 'cette'. Il a certainement tombe vers le bas si vous décidez plus tard de retourner quelque chose d'autre, comme un état/indicateur de réussite ou d'un message.
setPropertyAndGetObject();
a une chose, de définir une propriété. Bien sûr, je n'ai pas besoin de savoir comment le setter est implémente cet ensemble par exemple$A->setFullName($firstName, $lastName);
pouvez faire un peu de logique, par exemple, dans les différents pays, le nom de famille est le premier et premier nom est le deuxième. Mais il faire une seule chose: définit le nom complet.this
est fondamentale pour laBuilder
modèle. Mais, de retourthis
est aussi, de par sa conception avec un état de fonctionnement. Il n'y a pas de one-size-fits-all. Faveur de l'immuabilité. Le point de l'ensemble d'un constructeur (en général) est de faire de la construction d'un objet immuable failsafeCe n'est pas une mauvaise pratique. Il est de plus en plus une pratique courante. La plupart des langues ne vous oblige pas à traiter avec l'objet retourné si vous ne voulez pas de sorte qu'il ne change pas "normal" de poseur de syntaxe d'utilisation mais qui permet à la chaîne des setters ensemble.
Ce qui est communément appelé un générateur de motif ou un interface fluide.
Il est également fréquent dans l'API Java:
bla.foo.setBar1(...) ; bla.foo.setBar2(...)
quand vous pourriez écrirebla.foo /* newline indented */.setBar1(...) /* underneath previous setter */ .setBar2(...)
(ne peut pas utiliser des retours à la ligne (dans un commentaire comme celui-ci 🙁 ... j'espère que vous obtenez le point considérant 10 de ces incubateurs ou plus complexes des appels)Pour résumer:
Un couple d'autres points ne sont pas mentionnés:
Cela viole le principe que chaque fonction devrait faire un (et un seul) de la chose. Vous peut ou peut ne pas croire à cela, mais en Java je crois qu'il fonctionne bien.
IDEs ne vont pas générer ces pour vous (par défaut).
Je enfin, voici un monde réel point de données. J'ai eu des problèmes en utilisant une bibliothèque construite comme cela. Hibernate query builder est un exemple de cela dans une bibliothèque existante. Depuis Requête set* méthodes retournent des requêtes, il est impossible de le dire juste en regardant la signature de la façon de l'utiliser. Par exemple:
Il introduit une ambiguïté: la méthode de modifier l'objet courant (le patron) ou peut-être la Requête est vraiment immuable (très populaire et précieux, par exemple), et la méthode est de retour une nouvelle. Il fait juste de la bibliothèque plus difficile à utiliser, et beaucoup de programmeurs de ne pas exploiter cette fonctionnalité. Si les poseurs ont été setters, il serait plus claire de la façon de l'utiliser.
this
n'est guère complexe de la science de fusée. 🙂Je préfère utiliser " par " des méthodes pour cela:
Ainsi:
get
, unset
et unwith
pour chaque champ de la classe. C'est encore une solution intéressante, cependant. 🙂Project Lombok
's@Getter/@Setter
annotations... ce serait fantastique pour le chaînage. Ou vous pouvez utiliser quelque chose comme leKestrel
combinator (github.com/raganwald/Katy) que JQuery et Javascript démons de l'utilisation.void setFoo(Foo foo); Employee setFoo$(Foo foo)
(lewith
ne semble pas être une meilleure idée pour le con arguments pour moi)with
préfixe est une convention différente. comme @qualidafial a donné un exemple. méthodes avec le préfixewith
ne doit pas renvoyer dethis
mais plutôt une nouvelle instance comme l'instance en cours, maiswith
ce changement. Ceci est fait pour lorsque vous souhaitez que vos objets soient immuables. Alors quand je vois une méthode avec le préfixewith
je suppose que je vais avoir un nouvel objet, pas le même objet.Si vous ne voulez pas rentrer
'this'
de l'incubateur, mais ne voulez pas utiliser la deuxième option, vous pouvez utiliser la syntaxe suivante pour définir les propriétés:Que d'un côté je pense que c'est légèrement plus propre en C#:
equals
méthode. Il y a très propres moyens de traiter avec les classes anonymes dansequals
si vous savez ce que vous faites.Non seulement les sauts de la convention de getters/setters, il rompt également le Java 8 méthode de cadre de référence.
MyClass::setMyValue
est unBiConsumer<MyClass,MyValue>
, etmyInstance::setMyValue
est unConsumer<MyValue>
. Si vous avez votre setter retourthis
, alors ce n'est plus une instance valide deConsumer<MyValue>
, mais plutôt unFunction<MyValue,MyClass>
, et sera la cause de quelque chose en utilisant la méthode des références à ces setters (en supposant qu'ils sont des méthodes void) à la pause.Consumer<A>
etFunction<A,B>
en fournissant une implémentation par défaut devoid accept(A a) { apply(a); }
. Ensuite, il peut facilement être utilisé comme un et ne cassera pas le code qui exige une forme spécifique.Je ne sais pas Java, mais je l'ai fait en C++.
D'autres personnes l'ont dit, il rend les lignes à très long et très difficile à lire,
mais je l'ai fait comme ça des tas de fois:
C'est encore mieux:
au moins, je pense. Mais vous êtes les bienvenus à downvote moi et appelez-moi un terrible programmeur si vous le souhaitez. Et je ne sais pas si on peut même le faire en Java.
//
après chaque méthode, si vous configurez votre IDE de ne pas se joindre à déjà des lignes (par exemple, Eclipse > Propriétés > Java > Code > Formateur > retour à la Ligne > ne Jamais joindre à déjà des lignes).Ce schéma (pun intended), appelé "fluent interface", est en train de devenir très populaire aujourd'hui. C'est acceptable, mais ce n'est pas vraiment ma tasse de thé.
Car il n'a pas de retour void, il n'est plus valide JavaBean le setter de la propriété. Que peut-importe si vous êtes l'une des sept personnes dans le monde à l'aide de visual "Bean Builder" outils", ou de l'un des 17 à l'aide de JSP-bean-setProperty éléments.
Au moins en théorie, il peut endommager l'optimisation des mécanismes de la machine par la mise en fausses dépendances entre les appels.
Il est censé être en sucre syntaxique, mais en fait, peut créer des effets secondaires chez les super-intelligent Java 43 de la machine virtuelle.
C'est pourquoi je vote pas, ne l'utilisez pas.
set
méthode dépend de la premièreset
méthode bien qu'il soit connu par le programmeur.obj.modifyList(aList).modifyList(anotherList)
, oùmodifyList
ne modifie pasthis
, encore besoin de savoir ce quethis
est.-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining
La java7 jdk certainement inlines enchaîné méthodes, et n'environ le même nombre d'itérations qu'il faut pour marquer nulle setters comme à chaud et en ligne aussi. Il me semble que vous sous-estimez la puissance de la JVM de l'opcode de l'élagage des algorithmes; s'il sait que vous êtes de retour cette, il va sauter le jrs (java instruction return) opcode et il suffit de laisser ce sur la pile.Ce n'est pas une mauvaise pratique à tous. Mais ce n'est pas compatiable avec JavaBeans Spec.
Et il y a beaucoup de cahier des charges dépend de ces accesseurs standards.
Vous pouvez toujours les faire co-exister les uns aux autres.
Maintenant, nous pouvons les utiliser ensemble.
Voici une autre version pour objet immuable.
Maintenant nous pouvons le faire.
some
champ. Deuxièmement, vous devriez ajouter une clause de sauvegarde et de définirsome
ànull
dans le build() pourSome
est vraiment immuable, sinon on pourrait appelerbuilder.value()
sur la même instance de Générateur de nouveau. Et Enfin, oui, vous avez bien un constructeur, mais votreSome
a encore un constructeur public, ce qui signifie que vous n'avez pas prôner ouvertement l'utilisation du Générateur, c'est à dire que l'utilisateur ne connait pas d'autres que par l'essai ou la recherche d'une méthode pour définir une coutumevalue
à tous.Je suis en faveur de setters avoir "cette" les retours. Je n'ai pas de soins si ce n'est pas les haricots conforme. Pour moi, si c'est ok pour avoir le "=" expression/l'instruction, puis setters que les valeurs de retour est très bien.
Paulo Abrantes propose une autre façon de faire JavaBean setters couramment: définir intérieure d'un constructeur de la classe pour chaque JavaBean. Si vous êtes en utilisant des outils qui se déconcerté par les setters que les valeurs de retour, Paulo modèle pourrait aider.
Je préfère cette approche, mais j'ai décidé contre elle.
Raisons:
Le Générateur de modèle que j'ai vu ne pas utiliser le setFoo(foo).setBar(bar) de la convention, mais plus de foo(foo).bar(bar). Peut-être c'est précisément pour ces raisons.
C'est toujours une question de goût. J'aime juste les "moins de surprises" approche.
Ce modèle particulier est appelé le Chaînage de Méthode. Lien wikipédia, ce qui a davantage d'explications et d'exemples de la façon dont c'est fait dans divers langages de programmation.
P. S: Juste la pensée de le laisser ici, depuis que je suis à la recherche pour le nom spécifique.
Si vous utilisez la même convention dans l'ensemble de l'application, il semble bien.
Sur le sous-main si la partie existante de votre application utilise la norme de la convention, je garderais d'elle et d'ajouter que les constructeurs plus compliqué classes
À première vue: "Horrible!".
Sur la poursuite de la réflexion
est en fait moins d'erreurs que
Donc tout à fait intéressant. L'ajout de l'idée à l'toolbag ...
list
au début.Oui, je pense que c'est une bonne Idée.
Si je pouvais ajouter quelque chose, ce à propos de ce problème :
Cela fonctionne :
Ce ne sera pas acceptée par Eclipse ! :
C'est parce que setName() renvoie un Peuple et non pas un Ami, et il n'y a pas de PeoplesetNickName.
Comment pourrions-nous écrire des organismes de normalisation pour le retour de l'AUTO de la classe au lieu du nom de la classe ?
Quelque chose comme ce serait bien (si le mot-clé SELF existerait). N'existent de toute façon ?
class C<S extends C<S>>
, ce qui est plus sûr qu'un simpleS extends C
. a) SiA extends B
, etB extends C<B>
, et vous avez Un, vous ne savez que B est renvoyé à moins qu'Un des remplacements de chaque méthode. b) Vous ne pouvez pas désigner un local, non-rawC<C<C<C<C<...>>>>>
.En général c'est une bonne pratique, mais vous pourriez avoir besoin pour le type de fonctions de type Booléen pour déterminer si l'opération a réussi ou pas, c'est un de trop. En général, il n'y a pas de dogme à dire que c'est une bonne ou lit, il s'agit de la situation, bien sûr.
De la déclaration
je vois deux choses
1) déclaration vide de Sens.
2) le Manque de lisibilité.
Cela peut être moins lisible
ou ce
C'est beaucoup plus lisible que:
J'ai fait mes setters pour un bon moment et le seul vrai problème est avec les bibliothèques qui collent avec le strict getPropertyDescriptors pour obtenir le haricot lecteur/enregistreur de haricot accesseurs. Dans ces cas, votre java "haricot" n'aura pas les writters que vous attendez.
Par exemple, je ne l'ai pas testé, mais je ne serais pas surpris que Jackson ne reconnaît ceux que les setters lors de la création vous des objets java à partir de json/maps. J'espère que je me trompe sur ce point (je vais la tester au plus vite).
En fait, je suis en train d'élaborer un léger SQL centrée sur l'ORM et j'ai ajouter un peu de code au-delà de getPropertyDescriptors reconnus setters qui revient cette.
Il y a longtemps à répondre, mais mes deux cents ... Sa belle. Je souhaite à cette interface fluide ont été utilisés le plus souvent.
Répétition de la 'usine' variable de ne pas ajouter plus d'info ci-dessous:
C'est plus propre, à mon humble avis:
Bien sûr, comme l'une des réponses déjà mentionné, l'API Java faudrait être tordu pour le faire correctement pour certaines situations, comme l'héritage et des outils.
Il est préférable d'utiliser d'autres constructions de langage, si disponible. Par exemple, dans Kotlin, vous pouvez utiliser avec, appliquer, ou laisser. Si l'utilisation de cette approche, vous n'aurez pas vraiment besoin de retourner une instance de votre setter.
Cette approche permet à votre code client:
Voici quelques exemples.
Si je suis en train d'écrire une API, je vais utiliser le retour de cette" définition des valeurs qui ne sera définie qu'une seule fois. Si j'ai d'autres valeurs que l'utilisateur doit être en mesure de changer, j'utilise une norme nulle setter à la place.
Cependant, c'est vraiment une question de préférence et en enchaînant les poseurs n'a pas l'air tout à fait cool, à mon avis.
Je suis d'accord avec toutes les affiches affirmant cela rompt avec le JavaBeans spec. Il y a des raisons à préserver, mais j'ai aussi l'impression que l'utilisation de ce Générateur de Modèle (qui a été évoqué) a sa place; tant qu'il n'est pas utilisé partout, il devrait être acceptable. "Il la Place", pour moi, est le point final est un appel à un "build()" la méthode.
Il existe d'autres moyens de réglage de toutes ces choses, bien sûr, mais l'avantage ici est qu'il évite 1) de nombreux paramètres les constructeurs publics et 2) partiellement les objets spécifiés. Ici, vous avez le générateur de recueillir ce qu'il faut, et puis d'appeler sa "build()" à la fin, qui peut ensuite s'assurer que partiellement objet spécifié n'est pas construit, étant donné que l'opération peut être donné moins de visibilité publique. L'alternative serait de paramètre "objets", mais qui à mon humble avis pousse juste le problème d'un niveau.
Je n'aime pas beaucoup-paramètre constructeurs parce qu'il est plus probable que beaucoup de le même type d'arguments sont passés dans l', ce qui peut rendre plus facile à passer le mauvais arguments pour les paramètres. Je n'aime pas en utilisant beaucoup de setters parce que l'objet pourrait être utilisée avant d'être entièrement configuré. De plus, la notion d'ayant des valeurs par défaut basé sur des choix précédents est mieux servi avec un "build()" la méthode.
En bref, je pense que c'est une bonne pratique, si elle est utilisée correctement.
Mauvaise habitude:
un setter ensemble
un getter obtenir
qu'en déclarant explicitement une méthode, qui le fait pour U