Jusqu'ici, nous avons déclaré, dans une classe donnée, des membres qui ne portaient pas le modifieur
Si on imagine que l'on veuille, à un moment donné de l'exécution,
compter le nombre d'objets géométriques créés,
déclarer un integer dans la méthode
public class GeomObject { public static int nbCreatedObjects = 0; // nb d'objets créés - membre statique, existe de manière unique private String objName = "anonymous"; // membre non statique, existe pour chaque objet instancié }
Au sein de la classe GeomObject (et classes dérivées), on peut accéder à
public class Circle extends GeomObject { public Circle () { nbCreatedObjects++; } }
Mais, dans une autre classe (e.g. TestGeomObjects), comme un membre statique exisite indépendamment de tout objet instancié,
et comme c'est un membre "de classe",
on n'écrit pas
public class TestGeomObjects { public static void main (String args[]) { System.out.println(GeomObject.nbCreatedObjects); // possible car nbCreatedObjects existe même aucun objet n'a été instancié // (affiche 0) } }
De la même manière qu'il existe des membres statiques, il existe des méthodes statiques que l'on n'invoque pas sur un objet donné, mais sur une classe. Il existe différents cas pour lesquels l'utilisation de méthodes statiques est soit utile, soit nécessaire, que nous décrivons ci-dessous.
System.out.println (Math.max (3.2, 6.4)); System.out.println (Math.max (4, 2));
Dans la classe
if (obj == null) System.out.println ("null"); else System.out.println (obj.toString());
System.out.println ((obj == null) ? "null" : obj.toString());(inutile de retenir cette syntaxe, mais il faut pouvoir la déchiffrer si vous pouvez la rencontrez).
Une autre bonne raison de créer des méthodes statiques réside dans le besoin d'accéder aux membres statiques. Plus haut, nous avons déclaré un membre statique publique pour introduire cette notion. Mais il n'y a aucune bonne raison (dans ce cas) de rendre l'accès à ce membre publique. On peut écrire pour les membres de classes les mêmes méthodes (getters/setters) que pour les membres non statiques.
public class GeomObject { private static int nbCreatedObjects = 0 public static int getNbCreatedObjects () { return nbCreatedObjects; } // méthode pas nécessairement pertinente dans cet exemple public static void setNbCreatedObjects (nb) { // attention : ici, pas de this.nbCreatedObjects possible // this = "objet sur lequel on a invoqué la méthode". // Ici, on invoque une méthode "de classe" // => on ne l'invoque pas sur un objet nbCreatedObjects = nb; } public static void incNbCreatedObjects () { // accès au sein de la classe : pas besoin d'écrire GeomObject.nbCreatedObjects++ nbCreatedObjects++; } } public class TestGeomObjects { public static void main (String args[]) { System.out.println(GeomObject.getNbCreatedObjects()); // (affiche 0) GeomObject.incNbCreatedObjects (); GeomObject.incNbCreatedObjects (); System.out.println(GeomObject.getNbCreatedObjects()); // (affiche 2) GeomObject.setNbCreatedObjects (0); System.out.println(GeomObject.getNbCreatedObjects()); // (affiche 0) } }
Lorsque vous souhaitez regrouper les traitements récurrents que vous effectuez sur les instances d'une classe que vous avez conçue, le plus logique est souvent d'écrire ces traitements dans cette classe. Mais lorsque vous effectuez ces traitements récurrents sur une classe dont vous êtes l'utilisateur et non le concepteur (et si vous n'avez pas accès aux sources de cette classe), vous pouvez créer une classe dédiée à ces traitements.
Pour le projet d'extraction des triplets syntaxiques, vous pouvez être amenés à tester si un token est un verbe conjugué, un verbe à l'infinitif, un verbe tout court, si un token est sujet, etc. Vous pouvez ajouter des méthodes directement dans la classe Token :
public boolean isVerb () { return getPOS().startsWith("V"); } public boolean isInflectedVerb () { return ???; } public boolean isInfinitive () { return ???; } public boolean isSuj () { return getDepLabel().equals ("suj"); }
À l'extérieur de la classe (e.g. dans DependenciesBuilder),
vous pouvez invoquer ces méthodes sur des instances particulières de Token :
Si l'on imagine que vous n'ayez pas accès aux sources de la classe Token, vous pouvez créer une classe qui effectue les mêmes traitements :
package sajous.litl.token; public class TokenUtils { public static boolean isSuj (Token token) { return token.getDepLabel().equals("suj"); } public static boolean isCommonNoun (Token token) { return token.getPOS ().equals("NC"); } public static boolean isVerb (Token token) { return token.getPOS().startsWith("V"); } public Token getGovernor (Token token, Sentence sent) { Token result = null; // affectation a result du gouverneur de token return result; } public void relemmatize (Token token) { if (token.getLemma().equals("_")) { // appliquer heuristique pour deviner le lemme } } }Dans la classe DependenciesBuilder :
Sentence sent = reader.getSentence(); Token firstToken = sent.getToken(0); // declenche une exception (ArrayOutOfBoundException) si la phrase est vide System.out.println (TokenUtils.isNoun(firstToken)); System.out.println ("Gouverneur : " + TokenUtils.getGovernor (firstToken, sent);