Quelle est la différence entre les préfixes de nom de méthode "to" et "as" comme
- lister(),
- asList (),
- etc...
Quand utiliser lequel pour concevoir une méthode?
Quelle est la différence entre les préfixes de nom de méthode "to" et "as" comme
Quand utiliser lequel pour concevoir une méthode?
Réponses:
Une toXYZ()
fonction doit effectuer une conversion et renvoyer un nouvel objet indépendant (bien que l’immuabilité permette une optimisation, elle java.lang.String.toString()
ne renvoie que l’objet).
Par exemple, en C ++, nous avons std::bitset::to_ulong()
ce qui peut facilement échouer, et toute une pléthore de to_string()
conversions (plus ou moins) complexes et d’allocation de mémoire.
En asXYZ()
revanche, une fonction est supposée renvoyer une vue (potentiellement différente) de la source, en effectuant un travail minimal.
Par exemple, en C ++, nous avons std::as_const()
simplement une référence constante, et la plus impliquée, std::forward_as_tuple
qui fait également référence à ses arguments par référence.
std::to_string(x)
crée un nouvel objet chaîne, mais std::as_const(x)
crée une référence (une vue) de l'objet existant.
Honnêtement, il s’agit peut-être simplement de nommer une incohérence. Si certains objets de la bibliothèque standard dans Smalltalk, par exemple, toutes les méthodes qui font « conversions complexes » ou « retour de simples représentations dans un autre type » sont préfixés avec as
, comme asString
, asFloat
, asSeconds
et la méthode standard pour convertir quoi que ce soit à quoi que ce soit d' autre, as: aClass
.
Dans Ruby, les mêmes types de méthodes sont préfixées avec to_
, comme to_s
, to_a
, to_h
, court pour string
, array
et hash
respectivement.
Aucune des bibliothèques standard ne semble différencier les différents types de conversions, probablement parce que cela devrait être considéré comme un détail d'implémentation.
Cependant, en Java, nous voyons beaucoup de confusion. Comme vous l' avez mentionné, il y a toString
, asList
et ainsi de suite. Je pense que ce ne sont que des incohérences dans les noms, car si vous essayez de définir un sens différent pour chaque préfixe, vous trouverez toujours un contre-exemple ailleurs dans la bibliothèque standard.
Donc, dans tous les cas, je dirais que l’important est que vous et votre équipe choisissiez un préfixe et l’utilisiez de manière cohérente dans le code. La cohérence est la clé, de sorte que les gens ne sont pas laissés à se demander, comme vous le deviez.
toString
crée une nouvelle chaîne complètement déconnectée de l'objet (et il n'y a pas d'autre moyen à cause de l'immuabilité). Il en va de même, par exemple, pour Collection#toArray
, tandis que Arrays#asList
renvoie une vue du tableau qui est connecté de manière bidirectionnelle (la mutation du tableau modifie la liste et inversement). C'est donc assez cohérent, même s'il peut y avoir des exceptions. Choisir un préfixe serait une erreur. Si Arrays#toList
tel était le cas , je m'attendrais à ce qu'il crée une nouvelle liste avec un nouveau tableau sous-jacent.
Bien qu'il existe déjà une réponse acceptée, il semble se concentrer sur C ++, alors que la question est étiquetée avec Java . En Java, le premier exemple qui nous vient à l’esprit pour ce genre de chose est Arrays.asList , qui renvoie essentiellement une vue d’un tableau, encapsulée dans une liste. Le tableau sous-jacent et la liste sont toujours connectés. les modifications apportées au tableau sont reflétées dans la liste, et inversement. Cependant, le tableau renvoyé par la méthode toArray de la liste est indépendant du tableau d'origine et de la liste:
String[] wordArray = {"one", "fine", "day"};
List<String> wordList = Arrays.asList(wordArray);
// changes to the array are visible in the list
System.out.println(wordList); // prints "[one, fine, day]"
wordArray[1] = "horrible";
System.out.println(wordList); // prints "[one, horrible, day]"
// changes to the list are visible in the array
wordList.set(1, "beautiful");
System.out.println(wordArray[1]); // prints "beautiful"
// but changes to the list or array don't affect the
// result from the list's toArray method.
String[] moreWords = wordList.toArray(new String[] {});
wordList.set(0, "the");
wordArray[1] = "best";
for (int i=0; i<3; i++) {
System.out.println(moreWords[i]); // prints "one", "beautiful", and "day"
}
Cela dit, rien ne garantit que chaque développeur de bibliothèque respecte cette convention. Vous devez donc consulter la documentation pour savoir s'il s'agit du comportement que vous obtiendrez avec un code inconnu.
L'autre endroit que j'ai vu comme méthodes ... () est fréquemment utilisé pour la conversion de types en sous-types. Par exemple, si vous avez un ensemble énuméré de sous-types, vous pourriez alors vous retrouver avec un code comme:
/**
* Every Node is either an ANode or a BNode.
*/
interface Node {
/**
* Returns this Node as an ANode.
*
* @return this node
*/
default ANode asANode() {
if (this instanceof ANode) {
return (ANode) this;
}
else {
throw new UnsupportedOperationException();
}
// Or, in Java8 style, perhaps:
// return Optional.of(this)
// .filter(ANode.class::isInstance)
// .map(ANode.class::cast)
// .orElseThrow(UnsupportedOperationException::new);
}
/**
* Returns this Node as a BNode.
*
* @return this node
*/
default BNode asBNode() {
if (this instanceof BNode) {
return (BNode) this;
}
else {
throw new UnsupportedOperationException();
}
}
}
La différence que j’ai remarquée (juste maintenant en y réfléchissant) est que
Nous voyons donc AsInteger et AsString et nous voyons ToArray et ToStringList.
Impliquer une conversion qui a du sens (c'est un mouvement, un processus). Comme implique une représentation, une manière d’exprimer l’objet d’origine.
Une autre façon de regarder cela:
Et puis il y a "l'art antérieur" (ou l'héritage) à traiter. Avant que les langues soient totalement OO, vous disposiez de fonctions de bibliothèque telles que StrToInt () et IntToStr (). Ils effectuaient des conversions, c'étaient des opérations, il était donc logique de les appeler SomethingToSomethingelse (). Après tout, To est plus actif que As. Je pense particulièrement à Delphi ici.
Lorsque C # a été conçu avec l'ambition de devenir totalement opérationnel (OO), il était logique de disposer d'une méthode sur l'objet désormais entier qui convertirait l'entier en chaîne. Bien que nous ayons également une classe Convert, la conversion en chaîne est si courante qu'elle a été transformée en méthode virtuelle sur objet. Les concepteurs ont peut-être pensé que ToString serait plus familier aux personnes de l'ancien paradigme. C'est peut-être pour cette raison que nous avons obtenu une méthode virtuelle, ToString (), et non une propriété virtuelle, AsString.
toString()
?