Partage
  • Partager sur Facebook
  • Partager sur Twitter

problème avec "this" dans une méthode "static"

    26 mai 2009 à 15:00:50

    Bonjour à tous amis codeurs!! :D

    Je suis un peu débutant en Java et je galère pas mal sur mon projet de fin d'année.
    Mon problème à l'air simple mais me bloque depuis un bon moment.
    Voici mon code:
    private void affiche_menu() {
    
                super_label=new JLabel("Menu principal");
                super_label.setBounds(152,20,100,20);
                pan.add(super_label);
                super_label.setForeground(Color.RED);
                
                super_label=new JLabel("_____________");
                super_label.setBounds(150,30,100,15);
                pan.add(super_label);
                super_label.setForeground(Color.RED);
                
                super_bouton = new JButton("Créer un vol");
                super_bouton.addActionListener(this);
                super_bouton.setBounds(100,100,200,20);
                pan.add(super_bouton);
                ...
    


    Et voici mon problème:
    J'aimerai pouvoir appeler cette méthode depuis une autre. or, lorsque je l'appelle, eclipse me dit que je ne peux pas appeler une méthode non statique. Et dès lors que je la met en statique, il me souligne tous les "this" des "addActionListener" et me dit:"Cannot use this in a static context". :colere2:

    J'aimerai juste savoir comment résoudre ce problème. :(

    Merci à tous ceux qui auront au moins lu mon message. ;)

    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      26 mai 2009 à 15:07:21

      Tu ne peux pas vu que tu es dans le contexte de classe et que this est un contexte d'objet.
      • Partager sur Facebook
      • Partager sur Twitter
        26 mai 2009 à 15:11:01

        Tu l'appelle dans une méthode statique afficher_menu ?
        Tu ne peux pas utiliser de méthode non statique ni de variables non statiques dans des méthodes statiques, au pire crée le bouton et ajoute lui l'actionListener dans le constructeur de ta classe.
        Moi ce que je fais dans ces cas là c'est une classe avec un constructeur privé et une méthode qui renvoie un objet de cette classe, tout ce qui n'est pas statique je le met dans le constructeur, et tout ce qui est statique dans la méthode, et j'appelle le constructeur de la méthode statique, il n'y a que les constructeurs auxquels ont sais faire appel dans les méthodes statiques, à mon avis c'est fait exprès pour nous poussez à faire des classes "Factory."

        Exemple :
        public class LoginPage extends JPanel implements ActionListener {
        	private static Image loginbgimage;	
        	private static JTextField userName;
        	private static JPasswordField passwd, repasswd;	
        	private static WotckFrame parent;
        	private static JButton ok;
        	private static JButton sortir, annuler;
        	private static JButton inscription;	
        	private static JPanel centre, bas;	
        	private Graphics bufferGraphique;
        	private Image bufferImage;	
        	private TypeDialog type;
        	private static JDialog loginDialog;
        	private LoginPage (WotckFrame parent, TypeDialog type) {		
        		LoginPage.parent = parent;
        		this.type = type;
        		loginbgimage = TextureReader.readImage("images/loginpage.jpg", Toolkit.getDefaultToolkit(), new MediaTracker (this));
        		ok = new JButton ("Ok");
        		ok.addActionListener (this);
        		loginDialog = new JDialog (parent);
        		centre = new JPanel ();
        		centre.setBackground(new Color(115, 180, 255));
        		bas = new JPanel (new FlowLayout(FlowLayout.RIGHT));
        		bas.setBackground(new Color(115, 180, 255));
        		if (type == TypeDialog.LOGIN_DIALOG) {			
        			sortir = new JButton ("Sortir");
        			sortir.addActionListener(this);			
        			inscription = new JButton ("S'inscrire");
        			inscription.addActionListener(this);
        		} else if (type == TypeDialog.INSCRIPTION_DIALOG) {
        			annuler = new JButton("Annuler");
        			annuler.addActionListener(this);
        		}		
        		
        	}
        	
        	public static LoginPage createConnexionPage (WotckFrame parent) {	
        		
        		LoginPage cp = new LoginPage (parent, TypeDialog.LOGIN_DIALOG);		
        		loginDialog.setTitle("Connexion");
        		loginDialog.setLocationRelativeTo(parent);
        		loginDialog.setResizable(false);
        		loginDialog.addWindowListener(new LoginDialogListener ());			
        		
        		loginDialog.setLayout(new BorderLayout ());		
        		
        		centre.setLayout(new GridLayout (2, 2));
        		userName = new JTextField (10);
        		passwd = new JPasswordField (10);
        		JLabel usrname = new JLabel ("User name : ");
        		JLabel password = new JLabel ("Password : ");
        		centre.add(usrname);
        		centre.add(userName);
        		centre.add(password);
        		centre.add(passwd);
        		loginDialog.add(centre, BorderLayout.CENTER);
        		
        		bas.add(ok);
        		bas.add(inscription);
        		bas.add(sortir);
        		loginDialog.add(bas, BorderLayout.SOUTH);
        		loginDialog.pack();
        		loginDialog.setVisible(true);	
        		
        		return cp;		
        	}
        }
        

        • Partager sur Facebook
        • Partager sur Twitter
          26 mai 2009 à 15:30:47

          Ok, merci beaucoup, je vais méditer là dessus.
          • Partager sur Facebook
          • Partager sur Twitter
            27 mai 2009 à 9:52:01

            Désolé pour le retard, j'ai compris ce que tu as fait Lolilolight, mais je voulais savoir comment tu l'appelle ta classe (ou tes constructeurs) LoginPage.
            genre: monObjet = new LoginPage(uneVariable); :(

            Merci
            • Partager sur Facebook
            • Partager sur Twitter
              27 mai 2009 à 10:34:28

              Si ta méthode modifie des variables d'instance de ta classe, alors elle ne poura pas être statique. C'est logique : si tu souhaites modifier des comportements liés à un objet particulier, tu dois appliquer la méthode sur le dit objet.

              Si tu n'as besoin que d'un seul type d'objet, il va falloir passer sa référence dans toutes les classes l'utilisant. Cette référence, tu peux la passer au moyen de constructeur, de setter, du pattern Observer, et encore d'autres...
              • Partager sur Facebook
              • Partager sur Twitter
                27 mai 2009 à 10:44:44

                Il passe par une méthode statique, qui fera elle-même appel au constructeur :

                WotckFrame parent = ...;
                LoginPage monObject = LoginPage.createConnexionPage(parent);

                Au lieu de définir de nouveaux constructeurs, tu définis de nouvelles méthodes statiques (Qui feront éventuellement appel à d'autres constructeurs, privés).

                C'est le principe d'une Factory (L'intérêt, en général, étant plutôt "d'instancier des classes abstraites", mais c'est pas le sujet)

                Citation : Lolilolight

                il n'y a que les constructeurs auxquels ont sais faire appel dans les méthodes statiques, à mon avis c'est fait exprès pour nous poussez à faire des classes "Factory."



                Je ne suis pas sûr que tu comprennes bien la différence entre statique et... pas statique (Me semble qu'il y a un terme pour "pas statique", mais je l'ai plus en tête ^^ )

                Une méthode statique est spécifique à une classe, et non pas à une instance. Si tu essaies d'appeler une méthode non-statique à partir de là (= une méthode qui ne s'applique qu'à une instance), elle ne sait pas sur quel objet elle doit s'appliquer (Puisque dans ton contexte statique, tu n'as *aucun* objet, à moins d'en donner un explicitement).

                Quelques exemples et explications :

                - Les méthodes & instructions commentées sont celles qui sont invalides (Ou qui sont valides, mais appellent des méthodes invalides)
                - Le code compile & fonctionne

                package test;
                
                public class Test{
                	public static void main(String[] args){
                		/*
                		 method1(); //Impossible : On est dans un contexte statique ; il
                		//n'existe aucun objet. La méthode method1 n'est pas statique,
                		//et doit donc s'appliquer à un objet. Problème...
                		 */
                
                		Test myObject = new Test(); //Cette fois on a un objet
                
                		int result = myObject.method1(); //Et cette fois la méthode sait sur quel objet
                		//s'appliquer
                
                		System.out.println(result);
                	}
                
                	public int method1(){
                		return method2(); //Ici, on n'a pas besoin de spécifier
                		//l'objet : on est déjà "à l'intérieur" de l'objet (= dans le
                		//contexte de l'objet). Ne rien mettre revient à mettre "this",
                		//pas de soucis.
                	}
                
                	public int method2(){
                		/*
                		 return method3(); //Là, on appelle une méthode statique à
                		//partir du contexte d'un objet. Ca marche, ça va appeler la
                		//méthode sur la classe de l'objet dans lequel on se trouve.
                		//C'est équivalent à Test.method3()
                		 */
                		return method3(this); //Pour passer le contexte en
                		//paramètre à la bonne méthode, cf plus bas
                	}
                
                	/**
                	*	Version invalide
                	*/
                	
                	/*
                	 public static int method3(){
                		return method4(); //Contrairement à ce qu'on pourrait croire,
                		//*ça ne marche pas*. Bien que cette méthode soit appelée par
                		//method2(), qui est une méthode appliquée au contexte de
                		//"myObject", on se trouve désormais dans un nouveau contexte
                		//(statique = dans la classe Test, et non pas dans l'objet
                		//myObject). Comment faire alors ? Hé bien, soit on transforme
                		//cette méthode en "non statique", soit on lui passe l'objet
                		//en paramètre, afin de connaître le contexte
                	}
                	 */
                
                	/**
                	* 	Version valide
                	*/
                	public static int method3(Test object){
                		return object.method4();
                	}
                
                	public int method4(){
                		return 5;
                	}
                }
                


                Si vous avez compris ça, vous avez (presque) tout compris au static. Si vous ne pouvez pas appeler la méthode que vous voulez, ce n'est donc pas "pour inciter à utiliser des Factory", mais parce que vous avez un problème de conception de votre programme :)

                En résumé :

                - Le contexte statique est *unique* pour une classe, et il est partagé (implicitement) par toutes les instances de cette classe.

                - L'équivalent de "this" dans un contexte statique, c'est "le nom de la classe" :

                this.maMethodeDinstance(); //Contexte d'instance
                Test.maMethodeStatique(); //Contexte statique
                


                Il est possible de passer d'un contexte d'instance à un contexte statique de manière implicite (Sans utiliser le nom de la classe), mais *pas l'inverse* (Quand on est dans une méthode statique, il faut obligatoirement spécifier le nom de l'objet sur lequel on souhaite invoquer une méthode d'instance).
                • Partager sur Facebook
                • Partager sur Twitter
                  27 mai 2009 à 11:09:36

                  Ha oui mtnt je vois mieux, en fait ma méthode statique marche parce que je lui spécifie sur quel objet il faut appeler la méthode, l'objet lp que j'ai créer dnas ma méthode statique dans mon cas, tandis que le this ne marche pas, car pas d'objet dans un contexte statique donc il ne sais pas quel objet le this représente...

                  En gros il faudrait que dans l'addActionListener on remplace le this par le nom de l'objet.
                  Yes j'ai compris!

                  LoginPage cp = new LoginPage (parent, TypeDialog.LOGIN_DIALOG);		
                  loginDialog.setTitle("Connexion");
                  loginDialog.setLocationRelativeTo(parent);
                  loginDialog.setResizable(false);
                  loginDialog.addWindowListener(new LoginDialogListener ());			
                  		
                  loginDialog.setLayout(new BorderLayout ());		
                  ok.addActionListener (cp);
                  

                  Là maintenant il sais sur quel objet il doit placer l'actionListener!!
                  Merci, ça va simplifier grandement mon code.
                  Ha oui en plus le this représente l'objet sur lequel la méthode a été appelée, et comme une méthode statique n'est pas appelée sur un objet mais sur une classe, ça ne marche pas.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    29 mai 2009 à 10:11:41

                    Ok, merci tout le monde, j'ai appliqué vos conseils.
                    En gros, j'ai créé une classe avec un constructeur qui n'affecte que l'"action listener" au bouton. Je l'appelle en mettant juste "new BoutonListener". Et tout marche bien. :)
                    J'ai dû rater cet épisode dans le super tuto de cysboy! :-°

                    Merci à tous!
                    • Partager sur Facebook
                    • Partager sur Twitter

                    problème avec "this" dans une méthode "static"

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown