Est-il bon que toutes les fonctions setters renvoient une référence à l'objet en C++?Est-il bon que toutes les fonctions setters renvoient une référence à l'objet en C++?
Répondre
C'est un modèle suffisamment utilisable s'il y a beaucoup de choses qui doivent être définies sur un objet.
class Foo
{
int x, y, z;
public:
Foo &SetX(int x_) { x = x_; return *this; }
Foo &SetY(int y_) { y = y_; return *this; }
Foo &SetZ(int z_) { z = z_; return *this; }
};
int main()
{
Foo foo;
foo.SetX(1).SetY(2).SetZ(3);
}
Ce modèle remplace un constructeur qui prend trois ints:
int main()
{
Foo foo(1, 2, 3); // Less self-explanatory than the above version.
}
Il est utile si vous avez un certain nombre de valeurs qui ne doivent pas toujours être réglé.
Pour référence, un exemple plus complet de ce type de technique est référencé comme "Named Parameter Idiom" dans la FAQ C++ Lite.
Bien sûr, si vous utilisez ceci pour des paramètres nommés, vous pouvez jeter un oeil à boost::parameter. Ou vous pourriez ne pas ...
Je ne le pense pas. En règle générale, vous pensez que l'objet 'setter' fait exactement cela. En outre, si vous venez de définir l'objet, ne disposez-vous pas d'un pointeur de toute façon?
Tous les setters, mais certains d'entre eux pourraient renvoyer la référence à l'objet pour être utile.
genre de
a.SetValues(object)(2)(3)(5)("Hello")(1.4);
J'ai utilisé ce temps il y a une fois de temps pour construire le constructeur d'expression SQL qui gère tous les problèmes et autres évasions.
SqlBuilder builder;
builder.select(column1)(column2)(column3).
where("=")(column1, value1)
(column2, value2).
where(">")(column3, 100).
from(table1)("table2")("table3");
Je n'ai pas pu reproduire les sources en 10 minutes. Donc, la mise en œuvre est derrière les rideaux.
J'ai fait des choses similaires pour construire des documents XML en C++. La question ici semble cependant concerner les créateurs de propriété en général. –
Vous pouvez renvoyer une référence à this
si vous voulez la fonction setter de la chaîne appelle ensemble comme ceci:
obj.SetCount(10).SetName("Bob").SetColor(0x223344).SetWidth(35);
Personnellement, je pense que le code est plus difficile à lire que l'alternative:
obj.SetCount(10);
obj.SetName("Bob");
obj.SetColor(0x223344);
obj.SetWidth(35);
C'est une question de mise en page. Vous pouvez simplement écrire la première partie comme la seconde, en omettant obj. sur tout sauf le premier et; sur tout sauf le dernier. À mon humble avis, il est aussi lisible alors. –
Si votre motivation est liée à l'enchaînement (par exemple la suggestion de Brian Ensink), je voudrais offrir deux commentaires:
1. Si oui Vous trouverez souvent des réglages de plusieurs choses à la fois, ce qui peut signifier que vous devriez produire un struct
ou class
qui contient tous ces paramètres afin qu'ils puissent tous être transmis en même temps. La prochaine étape pourrait être d'utiliser struct
ou class
dans l'objet lui-même ... mais puisque vous utilisez des getters et des setters, la décision de le représenter en interne sera transparente pour les utilisateurs de la classe, donc cette décision relier plus à la complexité de la classe que quoi que ce soit.
2. Une alternative à un setter consiste à créer un nouvel objet, à le modifier et à le renvoyer. Ceci est à la fois inefficace et inapproprié dans la plupart des types, en particulier les types mutables. Cependant, c'est une option que les gens oublient parfois, malgré son utilisation dans la classe de chaînes de plusieurs langues.
Cette technique est utilisée dans Named parameter Idiom.
Le but typique de ce style est utilisé pour la construction d'objets.
Person* pPerson = &(new Person())->setAge(34).setId(55).setName("Jack");
au lieu de
Person* pPerson = new Person(34, 55, "Jack");
Utilisation du deuxième style plus traditionnel on peut oublier si la première valeur passée au constructeur était l'âge ou l'id? Cela peut également conduire à plusieurs constructeurs basés sur la validité de certaines propriétés. En utilisant le premier style, on peut oublier de définir certaines des propriétés de l'objet et peut conduire à des bogues où les objets ne sont pas «entièrement» construits. (Une propriété de classe est ajoutée ultérieurement mais tous les emplacements de construction n'ont pas été mis à jour pour appeler le setter requis.)
Comme le code évolue, j'aime vraiment le fait que je peux utiliser le compilateur pour m'aider à trouver tous les endroits où un objet est créé lors de la modification de la signature d'un constructeur. Donc, pour cette raison, je préfère utiliser les constructeurs C++ classiques sur ce style.
Ce modèle pourrait bien fonctionner dans des applications qui maintiennent leur datamodel au fil du temps selon des règles similaires à celles utilisées dans de nombreuses applications de base de données:
- Vous pouvez ajouter un champ/attribut à une table/classe qui est NULL par défaut. (La mise à niveau des données existantes requiert donc simplement une nouvelle colonne NULL dans la base de données.)
- Le code qui ne change pas devrait toujours fonctionner de la même manière avec ce champ NULL ajouté.
+1 pour la sécurité à la compilation. – Eclipse
Wow. C'est une adaptation étonnante au manque de paramètres nommés de C++ (comme Ada l'a fait depuis 20 ans). –
-> pas. pour les pointeurs si :) –
OMI setters sont une odeur de code qui indiquent généralement l'une des deux choses:
Faire un Mountian d'une taupinière
Si vous avez une classe comme ceci:
class Gizmo
{
public:
void setA(int a) { a_ = a; }
int getA() const { return a_; }
void setB(const std::string & b) { v_ = b; }
std::string getB() const { return b_; }
private:
std::string b_;
int a_;
};
... et les valeurs sont vraiment aussi simples, alors pourquoi ne pas simplement rendre les membres de données publics ?:
class Gizmo
{
public:
std::string b_;
int a_;
};
... Beaucoup plus simple et, si les données sont aussi simple que cela vous ne perdez rien.
Une autre possibilité est que vous pourriez être
Faire une taupinière Sur un Mountian
Beaucoup de fois que les données n'est pas aussi simple que cela: peut-être vous devez changer plusieurs valeurs, faire un peu de calcul, notifier un autre objet; qui sait quoi. Mais si les données sont assez triviales pour que vous ayez vraiment besoin de getters, alors c'est assez non-trivial pour avoir besoin de la gestion des erreurs. Donc, dans ces cas, vos setters & devraient renvoyer un code d'erreur ou faire quelque chose d'autre pour indiquer que quelque chose de mal est arrivé.
Si vous enchaînez les appels ensemble comme ceci:
A.doA().doB().doC();
... et DOA() tombe en panne, voulez-vous vraiment à appeler DOB() et doC() de toute façon? J'en doute.
RE: "A.doA(). DoB(). DoC();" Si DOA échoue, c'est ce que sont les exceptions. – Eclipse
+1, bon point John. Aussi bon point Josh. –
- 1. Est-ce que toutes les fonctions se déclenchent en retournant à une vue avec un UINavigation?
- 2. Bootstrap toutes les fonctions en PHP
- 3. Code de référence contenant toutes les constructions possibles en C
- 4. J'ai besoin de Référence et Explication de toutes les fonctions standard C
- 5. Passer par référence à travers plusieurs fonctions
- 6. Les requêtes ScriptResource.axd renvoient HTTP 302
- 7. Suivre toutes les références d'objet en C#
- 8. Comment passer une référence const en C#?
- 9. Minimisation toutes les fenêtres ouvertes en C#
- 10. Est-ce que lancer un objet en C# retourne toujours une référence à l'objet initial?
- 11. Pourquoi PHP requiert-il une référence explicite à "$ this" pour appeler les fonctions membres?
- 12. Que se passe-t-il lorsqu'on passe une référence à littéral en C++?
- 13. Consigner toutes les invocations de fonctions sur la console
- 14. Image Fonctions arithmétiques en C++
- 15. SÛR pointeur vers un pointeur (bien référence à une référence) en C#
- 16. Fonctions immuables en cache ou précalculées en C#/C++
- 17. C# Comment rendre les getters et setters publics et les méthodes privées pour une collection?
- 18. C++ Comment obtenir une référence et sauvegarder la référence en tant que variable locale dans une fonction?
- 19. Existe-t-il une référence pour les fonctions d'extension SharePoint XSLT?
- 20. Comment lister toutes les fonctions dans un module Python?
- 21. Comptage de référence en C++
- 22. Référence de fonctions similaires entre les langages de programmation
- 23. Un bon éditeur graphique CSS avec toutes les options CSS
- 24. C - Concaténer toutes les têtes d'une chaîne
- 25. Référence à la fonction Lua en C/C++
- 26. Les opérateurs peuvent-ils être utilisés en tant que fonctions? (C++)
- 27. Comment faire pour que les fonctions NOW() et CURDATE() de MySQL utilisent UTC?
- 28. Déduction des types de référence dans les fonctions de gabarit
- 29. Récupère toutes les fonctions définies pour un objet
- 30. Bon moyen de créer une boucle inactive en C#?
J'ai récemment été intrigué par cette technique. Ce sera intéressant de voir si quelqu'un a des inconvénients. –
Intéressant. Je n'avais pas considéré cela comme une alternative aux constructeurs complexes. Cette technique pourrait réduire le nombre de surcharges de constructeurs. –
Il y a certaines choses que vous ne pouvez pas faire avec ceci que vous pouvez faire avec les constructeurs (par exemple l'initialisation des consts et des références) – Eclipse