java et pointeurs sur fonction

java et pointeurs sur fonction - Java - Programmation

Marsh Posté le 08-04-2005 à 20:51:18    

Salut,
j'aimerai savoir si vous connaissez un moyen simple pour faire un equivalent de pointeur sur fonction en java
je rappelle le principe et mon but
 
en C, ca donnerait :
 
void fonc1() {}
void fonc2() {}
void fonc3() {}
 
void *myfonc
 
ensuite au choix
myfonc=&fonc1, myfonc=&fonc2 ou myfonc=&fonc3
 
sachant que les pointeurs en java ... et aussi, que je cherche pas de truc dans le genre
myfonc(String fonc) {
if (fonc=="fonc1" ) { ... }
if (fonc=="fonc2" ) { ... }
if (fonc=="fonc3" ) { ... }
}
 
bref, si vous avez des idées, je suis preneur
merci


---------------
The Rom's, à votre service
Reply

Marsh Posté le 08-04-2005 à 20:51:18   

Reply

Marsh Posté le 08-04-2005 à 22:04:04    

non, là le polymorphisme ne m'aide pas :
 
je veux pouvoir modifier le comportement de mon objet en modifiant ce qui est réalisé par une méthode "générique" que j'appellerai a partir d'un autre objet
 
p ex: un handler qui contiendrait un véhicule en appelant
handler.véhicule.avancer();
et véhicule.avancer() renverrait suivant le cas à
???.rouler(), ???.floter() ou ???.voler()
 
(??? paske je sais pas si ces fonctions doivent être dans véhicule ou ailleurs, peut etre une classe final avec un attribut static pour les méthodes ...)
 
bref, si vous savez comment faire ...


---------------
The Rom's, à votre service
Reply

Marsh Posté le 08-04-2005 à 22:44:11    

Il n'y a pas de concept de pointeur en Java, donc pas de pointeur sur fonctions ...
 
Cependant :
 

Citation :


The java equivalent of function pointers is the one-instance class, as used to pass handlers to swing components, for example. Often an anonymous class is used.
 
Put your function signature in an interface, and pass an object that implements that interface:
 
public Class1 {
  public interface CallBack {
    void myMethod(String arg1);
   }
 
  CallBack callb;
 
  public Class1(CallBack callb) {
   this.callb = callb;
   ..
   }
 
  .....
  callb.myMethod("A string" );
  }
 
class2 {
   .....
   first = new Class1(new Class1.CallBack() {
     public void myMethod(String arg1) {
       ... do something ...
     }});
...
}


---------------
Scheme is a programmable programming language ! I heard it through the grapevine !
Reply

Marsh Posté le 08-04-2005 à 23:10:59    

Ou bien: http://java.developpez.com/faq/jav [...] r_fonction
(mais pas testé)


---------------
[:whatde]
Reply

Marsh Posté le 08-04-2005 à 23:20:54    

oui effectivement ca a l'air pas mal, et donc il faut preparer plusieurs Class1.Callback et modifier first.callb quand on veut changer le comportement.
 
en fait ca doit même marcher avec des abstract. par contre pour utiliser la meme fonction générique dans plusieurs objets différents, et donc avec plusieurs comportements, ca fait ecrire pas mal de classe, limite une par comportement :( c moche
 
en tout cas, merci pour le conseil :)
 
edit: le second est sensiblement identique donc merci pour les conseils :D


Message édité par TheRom_S le 08-04-2005 à 23:26:30

---------------
The Rom's, à votre service
Reply

Marsh Posté le 09-04-2005 à 01:10:08    

TheRom_S a écrit :

en fait ca doit même marcher avec des abstract. par contre pour utiliser la meme fonction générique dans plusieurs objets différents, et donc avec plusieurs comportements, ca fait ecrire pas mal de classe, limite une par comportement :( c moche


en quoi c'est plus moche de devoir écire plusieurs classes plutot que de devoir écrire plusieurs méthodes ?

Reply

Marsh Posté le 09-04-2005 à 09:57:03    

bref pour résumer, une solution efficace serait :

Code :
  1. /* IFonctionpublic.java */
  2. public interface IFonctionPublic int execute(int,int);


Code :
  1. /* Func1.java */
  2. public class Func1 implements IFonctionPublic {
  3.      public int execute(int a, int b) { ... }
  4. }


Code :
  1. /* Func2.java */
  2. public class Func2 implements IFonctionPublic {
  3.      public int execute(int a, int b) { ... }
  4. }


Code :
  1. /* MonObjet.java */
  2. private IFonctionPublic ifp;
  3. public void setFunc(IFonctionPublic ifp) { this.ifp=ifp; }
  4. public int func(int a, int b) { return this.ifp.execute(a,b); }


 
effectivement, ca fait une classe par fonction et c'est moche
 
sinon, il reste :

Code :
  1. /* Comportements.java */
  2. public static int func1(int a,int b) { ... }
  3. public static int func2(int a,int b) { ... }


 

Code :
  1. /* MonObjet.java */
  2. int vara,varb,ret;
  3. public void setFunc(String name) {
  4.      if (name=="func1" ) { this.ret=Comportements.func1(this.vara,this.varb); }
  5.      if (name=="func2" ) { this.ret=Comportements.func2(this.vara,this.varb); }
  6. }
  7. public int func(int a, int b) {
  8.      this.vara=a;
  9.      this.varb=b;
  10.      retrun ret;
  11. }


 
finalement, il faut voir que même si les pointeurs n'existent pas en java, c'est parceque chaque variable ou méthode peut être assimilée à un pointeur. Donc ret garde le lien vers la bonne fonction ... dont le résultat change de valeur lorsqu'on change les valeurs des opérandes !
 
bon il reste le problème du choix if(name=="func..." ) mais ça évite de le garder dans la définition de la fonctionet de le balancer à chaque appel. C'est donc peut-être plus joli que de faire une classe par fonction ...


---------------
The Rom's, à votre service
Reply

Marsh Posté le 09-04-2005 à 10:03:46    

TheRom_S a écrit :

effectivement, ca fait une classe par fonction et c'est moche


mais y a rien de moche à ça, au contraire !  :sweat:  
(à part ta façon de définir une interface :o)
 
C'est très propre comme code. Bien plus qu'un pointeur de fonction à la con sur lequel tu risques de foirer ton passage d'argument parce qu'il n'y a aucun contrôle dessss.  
C'est utilisé très très couramment en programmation objet ...
 
 
sinon, ta 2e solution, oublie, c'est n'importe quoi. Et fais attention : en java, la comparaisont de chaine se fait avec la méthode equals, pas avec l'opérateur '=='


Message édité par benou le 09-04-2005 à 10:05:54
Reply

Marsh Posté le 09-04-2005 à 10:35:06    

effecitivement, je viens de tester la 2eme solution
ret n'est pas recalculé ! (uniquement lors de setFunc)
j'avais confondu avec un autre truc qui ressemble vaguement mais avec des fonctions et qu'on ne peut pas modifier :
 
classe 1 :
func() { ... class1.var ... }
 
classe 2 :
func() { return class1.func(); }
 
par contre, == fonctionne très bien
 
sinon, l'interface, c'est juste un copier/coller
 
donc je l'admet : j'ai écrit tout ca un peu vite et je suis grillé  :lol:


---------------
The Rom's, à votre service
Reply

Marsh Posté le 09-04-2005 à 10:55:19    

TheRom_S a écrit :

par contre, == fonctionne très bien


ouais 9 fois sur 10 ...

Reply

Marsh Posté le 09-04-2005 à 10:55:19   

Reply

Marsh Posté le 09-04-2005 à 13:38:32    

et le paquetage java.lang.reflect ne peut pas aider ? (une simple piste de recherche... je n'en suis pas sur)


---------------
TReVoR - http://dev.arqendra.net - http://info.arqendra.net
Reply

Marsh Posté le 09-04-2005 à 14:21:22    

ça peut, mais dans ce cas là c'est pas la meilleure solution.


---------------
Au royaume des sourds, les borgnes sont sourds.
Reply

Marsh Posté le 09-04-2005 à 14:54:27    

alors ca donnerait :
 

Code :
  1. /* MonObjet.java */
  2. private Method func;
  3. public void setFunc(String name) {
  4.    this.func=(new Comportement()).getClass().getDeclaredMethod(name,Class.forName("java.lang.Integer" ),Class.forName("java.lang.Integer" ));
  5. }
  6. public int func(int a, int b) {
  7.    // les méthodes de Comportement.java sont statiques ...
  8.    return (this.func.invoke(null,new Integer(a),new Integer(b))).intValue();
  9. }


là on voit qu'il faut passer par des classes donc pas d'int et invoke renvoie un Object donc un Integer ici ... à ce moment là, il vaut mieux ne plus utiliser d'int mais direct des Integer sinon on risque de surcharger le code ...
 
vous pensez que ça fonctionne ?
 
edit : faut rajouter un classcast ds le return d'aileurs ...


Message édité par TheRom_S le 09-04-2005 à 14:59:47

---------------
The Rom's, à votre service
Reply

Marsh Posté le 09-04-2005 à 14:57:44    

R3g a écrit :

ça peut, mais dans ce cas là c'est pas la meilleure solution.


 
A la limite, je prefere quand meme pour pas faire une classe par fonction
 
par contre je me demande si des erreurs peuvent passer facilement la compilation. y'a de bons controles ?


---------------
The Rom's, à votre service
Reply

Marsh Posté le 09-04-2005 à 18:12:05    

TheRom_S a écrit :

alors ca donnerait :
 

Code :
  1. /* MonObjet.java */
  2. private Method func;
  3. public void setFunc(String name) {
  4.    this.func=(new Comportement()).getClass().getDeclaredMethod(name,Class.forName("java.lang.Integer" ),Class.forName("java.lang.Integer" ));
  5. }
  6. public int func(int a, int b) {
  7.    // les méthodes de Comportement.java sont statiques ...
  8.    return (this.func.invoke(null,new Integer(a),new Integer(b))).intValue();
  9. }


là on voit qu'il faut passer par des classes donc pas d'int et invoke renvoie un Object donc un Integer ici ... à ce moment là, il vaut mieux ne plus utiliser d'int mais direct des Integer sinon on risque de surcharger le code ...
 
vous pensez que ça fonctionne ?
 
edit : faut rajouter un classcast ds le return d'aileurs ...


 
Ce code est horrible ! Utilise l'interface, c'est 100x plus object et fait pour traiter ce genre de problème. De +, flotter, rouler et voler ne correspondent pas de manière plus abstraite à bouger ?

Reply

Marsh Posté le 09-04-2005 à 18:21:24    

ah c'est sur qu'avec les transfos int <-> Integer, c'est horrible :D
par contre bouger est peut-être trop abstrait, que penses-tu de "seDeplacer" ? ;)


---------------
The Rom's, à votre service
Reply

Marsh Posté le 09-04-2005 à 18:24:50    

TheRom_S a écrit :

A la limite, je prefere quand meme pour pas faire une classe par fonction
 
par contre je me demande si des erreurs peuvent passer facilement la compilation. y'a de bons controles ?


A mon humble avis, tu as tort.
C'est courramment utilisé, même en C++, où on a pourtant les pointeurs sur fonction.
   http://google.com/search?q=strategy+pattern

Reply

Marsh Posté le 09-04-2005 à 19:02:14    

ben faut voir après à l'execution aussi.
c'est vrai que  
- object.getClass().getDeclaredMethod(String,Class.forName(),Class.forName())
et
- method.invoke(Object,args ...)
c'est surement lourd en ressources par rapport à la méthode des fonctions-objets
 
en fait en regardant les sources, y'a deja tout un tas de vérifications avant d'appeler sun.reflect.invoke(obj,args) dont j'ai pas les sources ...
 
ok je me rends -> une classe par fonction snif :ouimaitre:


---------------
The Rom's, à votre service
Reply

Marsh Posté le 09-04-2005 à 19:16:49    

TheRom_S a écrit :

ah c'est sur qu'avec les transfos int <-> Integer, c'est horrible :D
par contre bouger est peut-être trop abstrait, que penses-tu de "seDeplacer" ? ;)


 
C'est pas une question de conversion int / Integer en fait mais l'approche pas du tout orientée objet que tu prends et l'utilisation complètement exotique de la réflexion.
 
Je verrai bien un truc du genre:
 

Code :
  1. public interface IVehicule {
  2.    public void bouger(int a, int b) throws MouvementException;
  3. }
  4. public IBateau extends IVehicule {
  5. }
  6. public IVoiture extends IVehicule {
  7. }
  8. public IAvion extends IVehicule {
  9. }
  10. public class IGestionnaireVehicule {
  11.    private List vehicules = new ArrayList();
  12.    public void ajouterVehicule(IVehicule vehicule) {
  13.       // ...
  14.    }
  15.    public boolean supprimerVehicule(IVehicule vehicule) {
  16.       // ...
  17.    }
  18.    public void animer() {
  19.       // ...
  20.       for (Iterator it = vehicules.iterator() ; it.hasNext() ; ) {
  21.          IVehicule vehicule = (IVehicule) it.next();
  22.          vehicule.bouger(a, b);
  23.       }
  24.    }
  25. }

Reply

Marsh Posté le 09-04-2005 à 19:34:52    

je viens de découvrir java.lang.reflect donc ca peut etre exotique :)
d'ailleurs quelle est son utilisation principale ?
 
sinon, ton exemple est ok dans certains cas, mais pas pour une sorte de véhicule amphibie ...
en fait l'histoire est bien de pouvoir changer le comportement (ou sa stratégie j'ai l'impression qu'on dit) d'un objet "en live"


---------------
The Rom's, à votre service
Reply

Marsh Posté le 09-04-2005 à 19:41:27    

La réflexion permet d'interroger un objet pour qu'il te retourne dynamiquement sa description (entre autres), de créer des objets sans connaître leur type à l'avance...
 
En effet, pour une voiture amphibie, l'implémentation de bouger() doit être modifiée quand on passe de la terre à l'eau et vice versa. Mais ta voiture sachant qu'elle est amphibie devrait décider par elle-même de l'implémentation à utiliser. Comment ? Ton véhicule doit être "aware" :D du support sur lequel il repose. Ca pourrait être ton gestionnaire de véhicules qui les en informerait...
 
Ton véhicule amphibie est une sous-classe de voiture


Message édité par machinbidule1974 le 09-04-2005 à 19:42:30
Reply

Marsh Posté le 09-04-2005 à 19:59:27    

ok je vois pour la réflexion
 
par contre, l'exemple de la voitre, bouger, etc ... est peut-etre mauvais. ce que je cherchais, c'etait de faire evoluer un objet un peu comme si on voulait lui faire changer de classe ou plutot de sous-classe. une voiture qu'on voudrait transformer en avion ou un decodeur de protocole qui changerait d'algo de décodage suivant le proto encapsulé. en fait ca permet de garder l'objet sans detruire/recreer a chaque changement, ce qui peut demander un gros effort de passage de contexte. bref, tu fais toujours la meme chose vu de loin, mais le detail change en fonction du contexte ou de l'etat. ca peut aussi permettre de reduire la taille de ton objet : au lieu de contenir un decodeur différent pour chaque protocole succeptible d'etre rencontré (ds cet exemple là) tu en as toujours un seul (donc une classe simple) qui peut faire différentes opérations.


---------------
The Rom's, à votre service
Reply

Marsh Posté le 09-04-2005 à 20:01:07    

TheRom_S a écrit :

ok je vois pour la réflexion
 
par contre, l'exemple de la voitre, bouger, etc ... est peut-etre mauvais. ce que je cherchais, c'etait de faire evoluer un objet un peu comme si on voulait lui faire changer de classe ou plutot de sous-classe. une voiture qu'on voudrait transformer en avion ou un decodeur de protocole qui changerait d'algo de décodage suivant le proto encapsulé. en fait ca permet de garder l'objet sans detruire/recreer a chaque changement, ce qui peut demander un gros effort de passage de contexte. bref, tu fais toujours la meme chose vu de loin, mais le detail change en fonction du contexte ou de l'etat. ca peut aussi permettre de reduire la taille de ton objet : au lieu de contenir un decodeur différent pour chaque protocole succeptible d'etre rencontré (ds cet exemple là) tu en as toujours un seul (donc une classe simple) qui peut faire différentes opérations.


Tu as de la chance, le State Pattern s'implémente presque comme le Strategy Pattern. :)

Reply

Marsh Posté le 09-04-2005 à 20:47:15    

héhé les patterns !
je viens de faire un tour sur un site qui parle de design pattern en général
http://exciton.cs.rice.edu/JavaRes [...] nPatterns/
le decorator pattern à l'air interressant aussi pour faire evoluer un objet dynamiquement
merci Lam's pour les patterns


---------------
The Rom's, à votre service
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed