13 votes

Alternatives aux méthodes statiques en Java

Je suis en train de créer un mini ORM pour un programme Java que j'écris... il y a une classe pour chaque table de ma base de données, toutes héritant de ModelBase .

ModelBase est abstrait et fournit un ensemble de méthodes statiques pour trouver et lier des objets de la base de données, par exemple :

public static ArrayList findAll(Class cast_to_class) {
  //build the sql query & execute it 
}

Vous pouvez donc faire des choses comme ModelBase.findAll(Albums.class) pour obtenir une liste de tous les albums persistants. Mon problème est que dans ce contexte statique, je dois obtenir la chaîne sql appropriée de la classe concrète Album. Je ne peux pas avoir une méthode statique comme

public class Album extends ModelBase {
  public static String getSelectSQL() { return "select * from albums.....";}
}

car il n'y a pas de polymorphisme pour les méthodes statiques en Java. Mais je ne veux pas faire getSelectSQL() une méthode d'instance dans Album parce que je dois alors créer une instance de celui-ci pour obtenir une chaîne dont le comportement est vraiment statique.

En ce moment, findAll() utilise la réflexion pour obtenir le sql approprié pour la classe en question :

select_sql = (String)cast_to_class.getDeclaredMethod("getSelectSql", new Class[]{} ).invoke(null, null);

Mais c'est plutôt dégoûtant.

Alors, des idées ? C'est un problème général que je rencontre sans cesse : l'impossibilité de spécifier des méthodes statiques abstraites dans les classes ou les interfaces. Je sais que pourquoi Le polymorphisme des méthodes statiques ne fonctionne pas et ne peut pas fonctionner, mais cela ne m'empêche pas de vouloir l'utiliser à nouveau !

Existe-t-il un modèle/construction qui me permette de m'assurer que les sous-classes concrètes X et Y implémentent une méthode de classe (ou à défaut, une constante de classe !) ?

0voto

dalyons Points 723

Asterite : voulez-vous dire que getSelectSQL n'existe que dans ModelBase, et qu'il utilise la classe passée pour faire un nom de table ou quelque chose comme ça ? Je ne peux pas faire cela, parce que certains des modèles ont des constructions de sélection très différentes, donc je ne peux pas utiliser un "select * from " + classToTableName() ; universel. Et toute tentative d'obtenir des informations à partir des modèles sur leur construction de sélection se heurte au même problème que la question originale - vous avez besoin d'une instance du modèle ou d'une réflexion fantaisiste.

gizmo : Je vais certainement jeter un coup d'œil aux annotations. Mais je ne peux m'empêcher de me demander ce que les gens faisaient avec ces problèmes avant que la réflexion n'existe ?

0voto

Darren Greaves Points 1500

Vous pourriez avoir vos méthodes SQL comme méthodes d'instance dans une classe séparée.
Passez ensuite l'objet modèle dans le constructeur de cette nouvelle classe et appelez ses méthodes pour obtenir SQL.

0voto

Ewan Makepeace Points 1254

Wow - c'est un bien meilleur exemple de ce que j'ai demandé précédemment en termes plus généraux - comment implémenter des propriétés ou des méthodes qui sont statiques à chaque classe d'implémentation d'une manière qui évite la duplication, fournit un accès statique sans avoir besoin d'instancier la classe concernée et se sent "juste".

Réponse courte (Java ou .NET) : Vous ne pouvez pas. Réponse plus longue : vous pouvez le faire si cela ne vous dérange pas d'utiliser une annotation au niveau de la classe (réflexion) ou d'instancier un objet (méthode d'instance), mais aucune de ces méthodes n'est vraiment "propre".

Voir ma question précédente (connexe) ici : Comment gérer les champs statiques qui varient selon la classe d'implémentation ? J'ai trouvé que les réponses étaient toutes vraiment nulles et ne répondaient pas à la question. Votre question est bien mieux formulée.

-1voto

Tim Mooney Points 192

Je suis d'accord avec Gizmo : vous êtes soit à la recherche d'annotations ou d'une sorte de fichier de configuration. Je regarderais Hibernate et d'autres frameworks ORM (et peut-être même des bibliothèques comme log4j !) pour voir comment ils gèrent le chargement des méta-informations au niveau des classes.

Tout ne peut ou ne doit pas être fait de manière programmatique, je pense que c'est l'un de ces cas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X