J'ai une classe pleine de fonctions utilitaires. Instancier une instance de celui-ci n'a aucun sens sémantique, mais je veux toujours appeler ses méthodes. Quelle est la meilleure façon de gérer cela? Classe statique? Abstrait?
@matt b: Comme le souligne David Robles dans sa réponse, vous n'avez pas besoin de rendre la classe finale ... elle ne peut pas être sous-classée car une sous-classe ne pourra pas invoquer un constructeur de super classe car il est privé. Cependant ... pas de mal à être explicite. Mais jfyi :-).
Point 4: Appliquer la non-instabilité avec un constructeur privé
- Tenter d'imposer la non-instabilité en créant une classe abstraite ne fonctionne pas.
- Un constructeur par défaut n'est généré que si une classe ne contient aucun constructeur explicite, donc une classe peut être rendue non instanciable en incluant un constructeur privé:
// Noninstantiable utility classpublicclassUtilityClass{// Suppress default constructor for noninstantiabilityprivateUtilityClass(){thrownewAssertionError();}}
Étant donné que le constructeur explicite est privé, il est inaccessible en dehors de la classe. AssertionError n'est pas strictement obligatoire, mais il fournit une assurance au cas où le constructeur serait accidentellement appelé à partir de la classe. Il garantit que la classe ne sera jamais instanciée en aucune circonstance. Cet idiome est légèrement contre-intuitif, car le constructeur est fourni expressément afin qu'il ne puisse pas être invoqué. Il est donc judicieux d'inclure un commentaire, comme indiqué ci-dessus.
En tant qu'effet secondaire, cet idiome empêche également la classe d'être sous-classée. Tous les constructeurs doivent appeler un constructeur de superclasse, explicitement ou implicitement, et une sous-classe n'aurait aucun constructeur de superclasse accessible à invoquer.
On dirait que vous avez une classe utilitaire similaire à java.lang.Math .
L'approche est la classe finale avec un constructeur privé et des méthodes statiques.
Juste pour nager en amont, les membres statiques et les classes ne participent pas à l'OO et sont donc diaboliques. Non, pas mal, mais sérieusement, je recommanderais une classe régulière avec un modèle singleton pour l'accès. De cette façon, si vous avez besoin de remplacer le comportement dans tous les cas sur la route, ce n'est pas un réoutillage majeur. OO est votre ami :-)
singleton n'est pas plus mauvais que l'injection de dépendances :)
irréputable
12
OO a sa place, mais il y a des moments où ce n'est tout simplement pas pratique, ou ce serait un gaspillage de ressources - par exemple, quelque chose d'aussi simple que Math.abs (). Il n'y a aucune raison d'instancier un objet juste pour instancier un objet, alors qu'un appel de méthode statique vous aurait tout aussi bien servi sans aucune surcharge OO. ;)
rob
2
@rob re OO, je suis d'accord, Math.Abs n'a probablement jamais besoin d'une instance. Quand j'entends "j'ai une classe utilitaire", je vois Math.Avg (), où vous devez maintenant ajouter pris en charge pour une moyenne pondérée. Je vois un générateur d'URL, param in, url out qui doit être refactorisé pour prendre en charge href, ou url uniquement, etc. Aussi, maintenant je vais abandonner la tactique défensive OO standard, les tests! / me ducks
Bennett Dill
3
commentez les arguments du "constructeur privé": allez, les développeurs ne sont pas si stupides; mais ils SONT paresseux. créer un objet puis appeler des méthodes statiques? ça n'arrivera pas.
ne passez pas trop de temps à vous assurer que votre classe ne peut pas être mal utilisée. ayez confiance en vos collègues. et il existe toujours un moyen d'abuser de votre classe, quelle que soit la manière dont vous la protégez. la seule chose qui ne peut pas être mal utilisée est une chose qui est complètement inutile.
Quelqu'un qui a vu (dans le code de production, pas dans le code étudiant jsut) object.staticMethod Je pense que vous surestimez les capacités de Joe Random Programmer! :-P
TofuBeer
2
Classe finale et constructeur privé (bon mais pas indispensable)
Il ne sert à rien de déclarer la classe comme static. Déclarez simplement ses méthodes staticet appelez-les à partir du nom de la classe comme d'habitude, comme la classe Math de Java .
De plus, même s'il n'est pas strictement nécessaire de rendre le constructeur privé, c'est une bonne idée de le faire. Marquer le constructeur comme privé empêche d'autres personnes de créer des instances de votre classe, puis d'appeler des méthodes statiques à partir de ces instances. (Ces appels fonctionnent exactement de la même manière en Java, ils sont juste trompeurs et nuisent à la lisibilité de votre code.)
Réponses:
Constructeur privé et méthodes statiques sur une classe marquée comme finale.
la source
D'après le grand livre "Effective Java" :
Point 4: Appliquer la non-instabilité avec un constructeur privé
- Tenter d'imposer la non-instabilité en créant une classe abstraite ne fonctionne pas.
- Un constructeur par défaut n'est généré que si une classe ne contient aucun constructeur explicite, donc une classe peut être rendue non instanciable en incluant un constructeur privé:
Étant donné que le constructeur explicite est privé, il est inaccessible en dehors de la classe. AssertionError n'est pas strictement obligatoire, mais il fournit une assurance au cas où le constructeur serait accidentellement appelé à partir de la classe. Il garantit que la classe ne sera jamais instanciée en aucune circonstance. Cet idiome est légèrement contre-intuitif, car le constructeur est fourni expressément afin qu'il ne puisse pas être invoqué. Il est donc judicieux d'inclure un commentaire, comme indiqué ci-dessus.
En tant qu'effet secondaire, cet idiome empêche également la classe d'être sous-classée. Tous les constructeurs doivent appeler un constructeur de superclasse, explicitement ou implicitement, et une sous-classe n'aurait aucun constructeur de superclasse accessible à invoquer.
la source
AssertionError
sur d' autres alternatives commeIllegalStateException
,UnsupportedOperationException
, etc?On dirait que vous avez une classe utilitaire similaire à java.lang.Math .
L'approche est la classe finale avec un constructeur privé et des méthodes statiques.
Mais méfiez-vous de ce que cela fait pour la testabilité, je recommande de lire cet article
Les méthodes statiques sont mortes pour la testabilité
la source
Juste pour nager en amont, les membres statiques et les classes ne participent pas à l'OO et sont donc diaboliques. Non, pas mal, mais sérieusement, je recommanderais une classe régulière avec un modèle singleton pour l'accès. De cette façon, si vous avez besoin de remplacer le comportement dans tous les cas sur la route, ce n'est pas un réoutillage majeur. OO est votre ami :-)
Mon 0,02 $
la source
commentez les arguments du "constructeur privé": allez, les développeurs ne sont pas si stupides; mais ils SONT paresseux. créer un objet puis appeler des méthodes statiques? ça n'arrivera pas.
ne passez pas trop de temps à vous assurer que votre classe ne peut pas être mal utilisée. ayez confiance en vos collègues. et il existe toujours un moyen d'abuser de votre classe, quelle que soit la manière dont vous la protégez. la seule chose qui ne peut pas être mal utilisée est une chose qui est complètement inutile.
la source
la source
Il ne sert à rien de déclarer la classe comme
static
. Déclarez simplement ses méthodesstatic
et appelez-les à partir du nom de la classe comme d'habitude, comme la classe Math de Java .De plus, même s'il n'est pas strictement nécessaire de rendre le constructeur privé, c'est une bonne idée de le faire. Marquer le constructeur comme privé empêche d'autres personnes de créer des instances de votre classe, puis d'appeler des méthodes statiques à partir de ces instances. (Ces appels fonctionnent exactement de la même manière en Java, ils sont juste trompeurs et nuisent à la lisibilité de votre code.)
la source
Vous pouvez utiliser l'annotation @UtilityClass de lombok https://projectlombok.org/features/experimental/UtilityClass
la source