Précédent   Forum des professionnels en informatique > Java > Général Java
Général Java Java SE, Java ME, APIs, Persistance, JDBC, Spring, XML. Avant de poster -> FAQ Java, Sources Java
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 08/02/2012, 13h36   #1
Membre du Club
 
Inscription : octobre 2006
Messages : 102
Détails du profil
Informations forums :
Inscription : octobre 2006
Messages : 102
Points : 46
Points : 46
Par défaut Ajouter une méthode à une classe existante, sans héritage

Bonjour à tous,

Je pense avoir compris comment créer une sous-classe qui hérite (avec "extends") des méthode de sa classe-mère, mais je ne comprends pas comment enrichir une classe existante, sans modifier celle-ci, et sans créer de sous-classe.

Exemple, j'aimerais disposer d'une méthode qui me dit si une chaîne est un anagramme, je voudrais donc compléter la classe String par:

Code :
1
2
3
public boolean isAnagram () {
  // ...
}
de façon à pouvoir utiliser

Code :
1
2
3
4
String s1 = new String("kayak");
if (s1.isAnagram()) {
  // ...
}
Apparemment, si je crée un fichier String.java pour y déclarer cette méthode, plus aucune autre méthode de la classe n'est reconnue.

Comment faire ?

Merci d'avance,

G.
gvdmoort est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 13h49   #2
Nouveau Membre du Club
 
Inscription : janvier 2008
Messages : 75
Détails du profil
Informations forums :
Inscription : janvier 2008
Messages : 75
Points : 35
Points : 35
Ca doit pas être possible de modifier un .class (ici String.class), et vu que tu n'a pas accès au String.java originel, c'est raté.

Donc, à priori, héritage comme solution...
FrenchFrogger est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 13h52   #3
Modérateur
 
Avatar de Robin56
 
Homme Nicolas
Ingénieur développement logiciels
Inscription : juin 2009
Messages : 1 715
Détails du profil
Informations personnelles :
Nom : Homme Nicolas
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : juin 2009
Messages : 1 715
Points : 4 826
Points : 4 826
L'héritage est justement fais pour ça car là tu ne veux plus utiliser la classe String de base mais une classe custom. Tu peux faire une classe à côté sinon qui prend en paramètre un String tout simplement si la solution de la sous-classe ne te plait pas :
Code :
1
2
String s = "toto";
boolean b = StringUtilitaire.anagramme(s);
__________________
Robin56 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 14h03   #4
Modérateur
 
Avatar de tchize_
 
Homme
Responsable de service informatique
Inscription : avril 2007
Messages : 16 199
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 32
Localisation : Belgique

Informations professionnelles :
Activité : Responsable de service informatique
Secteur : Service public

Informations forums :
Inscription : avril 2007
Messages : 16 199
Points : 25 348
Points : 25 348
Envoyer un message via MSN à tchize_ Envoyer un message via Skype™ à tchize_
on ne peux pas faire de sous classe de String, String est final.
__________________
⥀⥁ Чиз faq java, cours java, javadoc. Pensez à et
"Votre génitrice tute des pédoncules au pandémonium" (le conjurateur, 1973)
tchize_ est déconnecté   Envoyer un message privé Réponse avec citation 50
Vieux 08/02/2012, 14h09   #5
Modérateur
 
Avatar de Robin56
 
Homme Nicolas
Ingénieur développement logiciels
Inscription : juin 2009
Messages : 1 715
Détails du profil
Informations personnelles :
Nom : Homme Nicolas
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : juin 2009
Messages : 1 715
Points : 4 826
Points : 4 826
Donc il ne te reste que la solution de la classe utilitaire.
__________________
Robin56 est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 08/02/2012, 14h33   #6
Membre émérite
 
Inscription : mai 2006
Messages : 787
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 787
Points : 837
Points : 837
Tout d'abord, il faut voir une classe ou une interface comme un contrat. C'est à dire que toute classe qui herite d'une autre classe ou qui implemente une interface devra definir les methodes de celles-ci.
Par exemple, si je prends une instance de object ou d'un de ses descendants, je suis sur d'avoir une méthode toString().

Pour ajouter une methode à une classe existante, il faut faire une sous classe. Par exemple, si Fils herite de Pere, Fils possedera toutes les fonctions de Pere plus celles qu'elle définira elle meme. Ainsi, Fils pourra etre utilisé partout ou Pere etait utilisé. En revanche, Pere ne pourra pas etre utilisé la ou Fils est utilisé.

Pour répondre à la question de base, il est possible d'ajouter une methode à une classe existante. Pour ca, tu peux regarder du coté de la programmation orientée Aspect.
Mais dans ton cas, il faut passer comme ca a été indiqué par une classe utilitaire.
hwoarang est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 14h59   #7
Expert Confirmé Sénior
 
Inscription : septembre 2004
Messages : 5 099
Détails du profil
Informations forums :
Inscription : septembre 2004
Messages : 5 099
Points : 7 025
Points : 7 025
Pour résumer :

Citation:
Envoyé par gvdmoort Voir le message
mais je ne comprends pas comment enrichir une classe existante, sans modifier celle-ci, et sans créer de sous-classe.
Normal que tu ne voies pas comment faire ça en Java, c'est impossible.
Et il est rare que ce soit gênant. Des solutions très raisonnables ont été proposées ici.
thelvin est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 15h15   #8
Modérateur
 
Inscription : août 2006
Messages : 2 848
Détails du profil
Informations forums :
Inscription : août 2006
Messages : 2 848
Points : 2 950
Points : 2 950
Tu peux aussi utiliser le pattern decorator, il me semble (à vérifier) :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
 
public class MyString {
 
	private String str;
 
	public MyString(String str) {
		this.str = str;
	}
 
	public int length() {
		return str.length();
	}
 
	public String substring(int index) {
		return str.substring(index);
	}
 
	public static void main(String[] args) {
		MyString str = new MyString("chaine");
		System.out.println(str.length());
	}
 
}
Ta classe encapsule un objet de type string.
Tu redéfinis toutes les méthodes de la classe String, mais qui font simplement appel à l'implémentation de ton objet String, comme pour length dans l'exemple.
Puis tu rajoutes les méthodes propres à ton implémentation.
C'est fastidieux puisque String a beaucoup de méthodes mais ça peut être parfois intéressant.
fr1man est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 21h24   #9
Membre confirmé
 
Inscription : juin 2005
Messages : 171
Détails du profil
Informations personnelles :
Âge : 29

Informations forums :
Inscription : juin 2005
Messages : 171
Points : 214
Points : 214
Bonjour,

Juste pour compléter le message de fr1man, le pattern Decorator nécessite que la classe décoratrice hérite d'une base commune à la class décorée.
Et ce afin que la classe décoratrice puisse être utilisé partout une un object décoré est attendu.

Donc ça donnerait :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class MyString extends String {
 
	private String str;
 
	public MyString(String str) {
		this.str = str;
	}
 
	public int length() {
		return str.length();
	}
 
	public String substring(int index) {
		return str.substring(index);
	}
 
        
        public boolean isAnagram () {
        // Calcul avec str
        }
	
        public static void main(String[] args) {
		MyString str = new MyString("chaine");
		
               System.out.println(str.isAnagram());
	}
 
}

Quoiqu'il en soit le pattern Décorator est une solution élégante dans le cas évoqué dans ce topic.
aurelman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 22h03   #10
Membre régulier
 
Homme Mikaël Gibert
Ingénieur développement logiciels
Inscription : septembre 2011
Messages : 31
Détails du profil
Informations personnelles :
Nom : Homme Mikaël Gibert
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : septembre 2011
Messages : 31
Points : 73
Points : 73
Je me permet d'ouvrir une petite parenthèse : il est tout à fait possible d'ajouter des méthodes à une classe sans héritage en utilisant des APIs "sauvages" permettant de manipuler le bytecode.

Avec Javassist :
Code :
1
2
3
4
5
6
7
 
ClassPool pool=ClassPool.getDefault();
Loader cl=new Loader(pool);
CtClass ct=pool.makeClass("myClass");
String myMethod = "public void myMethod() { System.out.println(\"youpi\"); }";
ct.addMethod(CtNewMethod.make(myMethod, ct));
ct.writeFile();
Bon ça fait longtemps que je n'ai pas touché à Javassist, mais ça a une tête du genre et, en tous cas, ça permet de faire entre autres ce genre de choses...
mikael.gibert est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 22h11   #11
Modérateur
 
Avatar de tchize_
 
Homme
Responsable de service informatique
Inscription : avril 2007
Messages : 16 199
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 32
Localisation : Belgique

Informations professionnelles :
Activité : Responsable de service informatique
Secteur : Service public

Informations forums :
Inscription : avril 2007
Messages : 16 199
Points : 25 348
Points : 25 348
Envoyer un message via MSN à tchize_ Envoyer un message via Skype™ à tchize_
Pour rappel, on parle là d'un problème de débutant par rapport au language, donc les modifications sauvage d'une classe de java.lang on oublie, et l'orienté aspect aussi. C'est sortir les cuirassé pour souffler une mouche morte!

Donc, non, en java, on n'ajoute pas une méthode à une classe existante, on utilise l'héritage pour ça. Et non, ce n'est donc pas applicable à String puisque cette classe est final.
__________________
⥀⥁ Чиз faq java, cours java, javadoc. Pensez à et
"Votre génitrice tute des pédoncules au pandémonium" (le conjurateur, 1973)
tchize_ est déconnecté   Envoyer un message privé Réponse avec citation 40
Vieux 09/02/2012, 09h18   #12
Membre Expert
 
Homme
Ingénieur développement logiciels
Inscription : septembre 2008
Messages : 733
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : septembre 2008
Messages : 733
Points : 1 397
Points : 1 397
Il est clair que le problème ici est un problème de compréhension par l'auteur. Et de tels bidouillages sont franchement à bannir.
deathness est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2012, 09h53   #13
Membre émérite
 
Inscription : mai 2006
Messages : 787
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 787
Points : 837
Points : 837
Citation:
Envoyé par aurelman Voir le message
Juste pour compléter le message de fr1man, le pattern Decorator nécessite que la classe décoratrice hérite d'une base commune à la class décorée.
Et ce afin que la classe décoratrice puisse être utilisé partout une un object décoré est attendu.
Sauf que String est final donc c'est pas possible


Citation:
Envoyé par tchize_ Voir le message
Pour rappel, on parle là d'un problème de débutant par rapport au language, donc les modifications sauvage d'une classe de java.lang on oublie, et l'orienté aspect aussi. C'est sortir les cuirassé pour souffler une mouche morte!
Oui mais ca n'empeche pas de parler de techniques qui permettraient de faire ca. Peut etre que certains qui vont tomber sur ce topic à travers un moteur de recherche seront contents de trouver une réponse. Mais sur le fond, je suis d'accord pour dire que ce ne sont pas les techniques à utiliser pour le probleme dont on parle (mais les solutions ont deja été données des le début...)
hwoarang est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2012, 15h24   #14
Membre confirmé
 
Inscription : juin 2005
Messages : 171
Détails du profil
Informations personnelles :
Âge : 29

Informations forums :
Inscription : juin 2005
Messages : 171
Points : 214
Points : 214
Citation:
Envoyé par hwoarang Voir le message
Sauf que String est final donc c'est pas possible
Ben oui c'est vrai ça ! au temps pour moi )

Donc pas d'héritage de String.

Donc soit une classe Utilitaire avec une méthode prenant une String en parametre et retournant un booleen. La méthode triviale

Une classe wrapper, un peu sur le model du Décorator mais sans l'héritage... ou au pire un Décorator avec héritage de l'interface CharSequence pour garder un peu de souplesse (mais est-ce vraiment utile vu le besoin initial ...)
aurelman est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2012, 16h09   #15
Modérateur
 
Avatar de tchize_
 
Homme
Responsable de service informatique
Inscription : avril 2007
Messages : 16 199
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 32
Localisation : Belgique

Informations professionnelles :
Activité : Responsable de service informatique
Secteur : Service public

Informations forums :
Inscription : avril 2007
Messages : 16 199
Points : 25 348
Points : 25 348
Envoyer un message via MSN à tchize_ Envoyer un message via Skype™ à tchize_
j'avoue qu'en bientot 8 ans d'usage professionnel de java, je n'ai jamais eu besoin d'ajouter une méthode dans String
__________________
⥀⥁ Чиз faq java, cours java, javadoc. Pensez à et
"Votre génitrice tute des pédoncules au pandémonium" (le conjurateur, 1973)
tchize_ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2012, 16h11   #16
Membre Expert
 
Homme
Ingénieur développement logiciels
Inscription : septembre 2008
Messages : 733
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : septembre 2008
Messages : 733
Points : 1 397
Points : 1 397
Citation:
Envoyé par tchize_ Voir le message
j'avoue qu'en bientot 8 ans d'usage professionnel de java, je n'ai jamais eu besoin d'ajouter une méthode dans String
T'es pas joueur c'est pour ça
deathness est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2012, 17h05   #17
Membre éprouvé
 
Homme Eric
Inscription : décembre 2010
Messages : 254
Détails du profil
Informations personnelles :
Nom : Homme Eric
Localisation : France

Informations forums :
Inscription : décembre 2010
Messages : 254
Points : 450
Points : 450
Pour ce qui est de modifier la classe String par des moyens détournés, il me semble que de toutes façons les JVM standard sont, pour des raison de sécurité, protégées contre les redéfinition du contenu de java.lang, donc sauf à modifier le JRE (du genre patcher la bilbiothèque de base qui contient java.lang), on ne peut pas "bidouiller" String.
therwald est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2012, 20h01   #18
Modérateur
 
Avatar de tchize_
 
Homme
Responsable de service informatique
Inscription : avril 2007
Messages : 16 199
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 32
Localisation : Belgique

Informations professionnelles :
Activité : Responsable de service informatique
Secteur : Service public

Informations forums :
Inscription : avril 2007
Messages : 16 199
Points : 25 348
Points : 25 348
Envoyer un message via MSN à tchize_ Envoyer un message via Skype™ à tchize_
avec aop et compagnie, tu ne sait rien faire, que ce soit dans java.lang ou autre chose, si t'es dans un environnement avec un securitymanager (applet, webstart, certains serveurs J2EE)
__________________
⥀⥁ Чиз faq java, cours java, javadoc. Pensez à et
"Votre génitrice tute des pédoncules au pandémonium" (le conjurateur, 1973)
tchize_ est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 21h06.


 
 
 
 
Partenaires

Hébergement Web