CodeGym /Blog Java /Random-FR /Cours anonymes
Auteur
John Selawsky
Senior Java Developer and Tutor at LearningTree

Cours anonymes

Publié dans le groupe Random-FR
Salut! Dans la leçon d'aujourd'hui, nous allons continuer à examiner le sujet des classes imbriquées. C'est maintenant au tour du dernier groupe : les classes internes anonymes. Revenons à notre schéma : Cours anonymes - 2Comme les classes locales dont nous avons parlé dans la dernière leçon, les classes anonymes sont une sorte de classe interne... Elles ont aussi plusieurs similitudes et différences. Mais d'abord, plongeons-nous dans les détails : pourquoi sont-ils exactement appelés "anonymes" ? Pour y répondre, considérons un exemple simple. Imaginez que nous ayons un programme de base qui tourne constamment et fait quelque chose. Nous voulons créer un système de suivi de ce programme, composé de plusieurs modules. Un module suivra les indicateurs généraux de performance et maintiendra un journal. Le second enregistrera et enregistrera les erreurs dans un journal des erreurs. Le troisième suivra les activités suspectes : par exemple, les tentatives d'accès non autorisées et d'autres éléments liés à la sécurité. Étant donné que les trois modules doivent, en substance, simplement commencer au début du programme et s'exécuter en arrière-plan,

public interface MonitoringSystem {
  
   public void startMonitoring();
}
3 classes concrètes vont l'implémenter :

public class GeneralIndicatorMonitoringModule implements MonitoringSystem {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor security!");
   }
}
Il semblerait que tout soit en ordre. Nous avons un système assez cohérent composé de plusieurs modules. Chacun d'eux a son propre comportement. Si nous avons besoin de nouveaux modules, nous pouvons les ajouter, car nous avons une interface assez facile à mettre en œuvre. Mais réfléchissons au fonctionnement de notre système de surveillance. Cours anonymes - 3Fondamentalement, nous avons juste besoin de créer 3 objets — GeneralIndicatorMonitoringModule, ErrorMonitoringModule, SecurityModule— et d'appeler la startMonitoring()méthode sur chacun d'eux. Autrement dit, tout ce que nous devons faire est de créer 3 objets et d'appeler 1 méthode dessus.

public class Main {

   public static void main(String[] args) {

       GeneralIndicatorMonitoringModule generalModule = new GeneralIndicatorMonitoringModule();
       ErrorMonitoringModule errorModule = new ErrorMonitoringModule();
       SecurityModule securityModule = new SecurityModule();

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Sortie console :

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
Et avec si peu de travail, nous avons écrit tout le système : 3 classes et une interface ! Et tout cela pour arriver à 6 lignes de code. D'autre part, quelles sont nos options ? Eh bien, ce n'est pas très cool que nous ayons écrit ces cours "ponctuels". Mais comment pouvons-nous résoudre ce problème ? Ici, les classes internes anonymes viennent à notre secours ! Voici à quoi ils ressemblent dans notre cas :

public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor general indicators!");
           }
       };

       

MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor security!");
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Découvrons ce qui se passe ! Il semble que nous créons un objet d'interface :

MonitoringSystem generalModule = new MonitoringSystem() {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
};
Mais nous savons depuis longtemps que nous ne pouvons pas créer d'objets d'interface ! Et c'est ainsi — c'est impossible. En fait, ce n'est pas ce que nous faisons. Quand on écrit :

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
ce qui suit se produit à l'intérieur de la machine Java :
  1. Une classe Java sans nom est créée pour implémenter l' MonitoringSysteminterface.
  2. Lorsque le compilateur voit une telle classe, il vous demande d'implémenter toutes les méthodes de l' MonitoringSysteminterface (nous l'avons fait 3 fois).
  3. Un objet de cette classe est créé. Attention au code :

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
Il y a un point-virgule à la fin ! Il est là pour une raison. Nous déclarons simultanément la classe (en utilisant des accolades) et en créons une instance (en utilisant ();). Chacun de nos trois objets remplace la startMonitoring()méthode à sa manière. Enfin, on appelle simplement cette méthode sur chacun d'eux :

generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
Sortie console :

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
C'est ça! Nous avons atteint notre objectif : nous avons créé trois MonitoringSystemobjets, remplacé une méthode de trois manières différentes et l'avons appelée trois fois. Les trois modules ont été appelés avec succès et sont en cours d'exécution. En même temps, la structure de notre programme est devenue beaucoup plus simple ! Après tout, les classes GeneralIndicatorMonitoringModule, ErrorMonitoringModuleet SecurityModulepeuvent désormais être entièrement supprimées du programme ! Nous n'en avons tout simplement pas besoin - nous avons fait un excellent travail sans eux. Si chacune de nos classes anonymes a besoin d'un comportement différent, par exemple ses propres méthodes spécifiques que les autres n'ont pas, nous pouvons facilement les ajouter :

MonitoringSystem generalModule = new MonitoringSystem() {
  
   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
  
   public void someSpecificMethod() {

       System.out.println("Specific method only for the first module");
   }
};
La documentation Oracle fournit une bonne recommandation : "Utilisez [des classes anonymes] si vous n'avez besoin d'utiliser une classe locale qu'une seule fois." Une classe anonyme est une classe interne à part entière. En conséquence, il a accès aux variables de la classe externe, y compris les variables statiques et privées :

public class Main {

   private static int currentErrorCount = 23;

   public static void main(String[] args) {

       MonitoringSystem errorModule = new MonitoringSystem() {
          
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }

           public int getCurrentErrorCount() {

               return currentErrorCount;
           }
       };
   }
}
Elles ont quelque chose en commun avec les classes locales : elles ne sont visibles qu'à l'intérieur de la méthode dans laquelle elles sont déclarées. Dans l'exemple ci-dessus, toute tentative d'accès à l' errorModuleobjet en dehors de la main()méthode échouera. Et il y a une autre limitation importante que les classes anonymes héritent de leurs "ancêtres" (classes internes) : une classe anonyme ne peut pas contenir de variables et de méthodes statiques . Dans l'exemple ci-dessus, si nous essayons de rendre la getCurrentErrorCount()méthode statique, le compilateur générera une erreur :

// Error! Inner classes cannot have static declarations
public static int getCurrentErrorCount() {

   return currentErrorCount;
}
Nous obtenons le même résultat si nous essayons de déclarer une variable statique :

MonitoringSystem errorModule = new MonitoringSystem() {

   // Error! Inner classes cannot have static declarations!
   static int staticInt = 10;

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }

};
Et notre leçon d'aujourd'hui est terminée ! Mais même si nous avons étudié le dernier groupe de classes imbriquées, nous n'avons pas encore terminé ce sujet. Qu'allons-nous apprendre de plus sur les classes imbriquées ? Vous le saurez certainement bientôt ! :)
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION