2009-12-28 5 views
1

Je voudrais écrire une classe abstraite (ou interface) qui soitComment spécifier qu'une classe d'implémentation doit contenir un champ particulier?

  • Forces toutes les classes implémentant pour fournir un champ (idéalement statique) d'un type particulier et le nom (peut-être en jetant une erreur de compilation si il est manquant?), ou
  • Fournit automatiquement de tels champs dans les classes d'implémentation.

Un exemple serait:

public abstract class A { 
    abstract int counter; 
} 

public class B extends A { 
    public int getCounter() { 
     return counter; 
    } 
} 

auquel cas la méthode B de getCounter() reviendrait un (statique ou par exemple) counterspécifique à la classeB, et non une valeur héritée deA . Y a-t-il un moyen de le faire en Java?

+0

Pourquoi doit-il être statique? Si une interface a ... public int getCounter(); est-ce important si la classe d'implémentation l'exécute de manière statique ou non (peut-être garde-t-elle la trace du compteur dans une base de données). Je ne vois pas pourquoi vous auriez besoin de restreindre cela. – Pace

Répondre

8

Il n'y a pas vraiment un bon moyen de le faire, et je ne crois pas qu'il devrait y avoir. Vous pouvez accomplir la même chose en utilisant des méthodes abstraites et en écrivant vos algorithmes dans la classe de base afin qu'ils tirent parti des méthodes déléguées. Peut-être que si vous fournissez plus de détails sur les raisons pour lesquelles vous pensez devoir faire cela, nous pouvons vous aider à trouver une solution plus correcte.

Par exemple:

public abstract class A { 

    protected abstract int getCounter(); 

    public void doStuff() { 
     int counter = getCounter(); 
     for (int i=0; i < counter; i++) { 
      // do stuff 
     } 
    } 

} 
+0

Chaque classe qui implémente A a besoin de sa propre copie d'une variable (statique, idéalement) nommée 'counter', et d'un getter pour ce compteur. Pour minimiser le code en double, j'espérais avoir un moyen d'écrire une méthode getter dans A qui retourne effectivement le compteur de B. En effet, il y aura une classe abstraite «modèle» (ou interface) A, mais de nombreuses classes d'implémentation similaires qui ressemblent à B. –

+0

Il ne semble pas nécessaire que la variable soit statique. Mon exemple devrait faire ce que vous voulez. – Kevin

1

Faire un HashMap avec la classe comme la clé, et le compteur en tant que valeur.

+0

Cela semble horrible et plutôt inélégant pour moi. J'essaye d'écrire moins de code, pas plus. –

+0

mais cela me semble plutôt approprié. "moins de code" n'est pas toujours approprié. (btw, Thorbjorn - désolé, hors upvotes pour aujourd'hui) – Bozho

+0

this.getClass() peut vous obtenir un peu du chemin. –

1

L'objectif principal d'une interface n'est pas de dire à ses implémenteurs quoi faire. C'est pour dire aux autres classes ce que ses implémenteurs peuvent faire avec. En outre, il ne doit pas spécifier de détails d'implémentation. Cela dit, il ne devrait pas et ne peut imposer aucune déclaration variable.

Si vous voulez un par sous-classe contre, puis déclarer une Map dans la superclasse, avec la clé = sous-classe de Class et valeur = la valeur du compteur (comme le suggère la réponse de Thorbjørn Ravn Andersen)

+0

C'est pourquoi je pense principalement à faire cela avec un cours abstrait. –

+0

Les classes abstraites spécifient également "une interface". Bien que pas strictement à travers le mot-clé de l'interface. – Bozho

0

Essayez l'un des les nombreux outils énumérés ici:

http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis#Java

Je suppose que c'est dans un environnement de développement avec plusieurs développeurs.

+0

En quoi est-ce pertinent ..? – Bozho

+0

Oui, c'est pertinent. C'est * A * façon d'imposer les choses qu'il veut – Woot4Moo

+0

Je ne suis pas le seul dans ma boutique, mais je suis le seul (dans un avenir prévisible) à écrire des classes qui mettent en œuvre A. Je veux me forcer à écrire cohérent implémentations. –

0

Comme d'autres l'ont fait remarquer, ce n'est pas directement possible dans la langue sans beaucoup de travail supplémentaire.

Ma suggestion est que vous suiviez la suggestion de Pace: au lieu de spécifier un compteur, spécifiez-le comme une méthode dans une interface. La seule différence que je suggère est que vous le renommez en quelque chose qui reflète plus correctement votre intention.Quelque chose comme:


    protected abstract getNumberOfInstancesOfThisClass(); 

Vous pouvez coder même jusqu'à un générateur de test unitaire automatisé pour vérifier qu'il a été correctement mis en œuvre, quelque chose que vous auriez à faire même si vous pouvez créer un membre statique dans une classe abstraite.

0
public abstract class A { 
    private static Map<Class,Integer> map = new HashMap<Class,Integer>(); 
    protected A() { map.put(this.getClass(), 0); } 

    public int getCounter() { return map.get(this.getClass()); } 
    public void setCounter(int n) { map.put(this.getClass(), n); } 
} 

public class B extends A { 
    ...  
}