Apprendre Java pour le développement Android Inner Classes

Dans ce tutoriel, vous allez vous familiariser avec le concept de classes internes en Java, ces classes dont la portée et la définition sont englobées dans une autre classe. Vous découvrirez également les classes internes anonymes, qui sont fréquemment utilisées lors du développement avec le SDK Android..

Les applications Android sont écrites en Java, un langage de programmation orienté objet. Dans ce tutoriel, vous en apprendrez plus sur les classes internes, quand et pourquoi les utiliser, et comment elles fonctionnent. Vous apprendrez également à créer de nouveaux objets de manière dynamique à l'aide de classes internes anonymes..

Ce dont vous aurez besoin

Techniquement, vous n'avez besoin d'aucun outil pour compléter ce didacticiel, mais vous en aurez certainement besoin pour développer des applications Android..

Pour développer des applications Android (ou des applications Java, d'ailleurs), vous avez besoin d'un environnement de développement pour écrire et créer des applications. Eclipse est un environnement de développement (IDE) très populaire pour Java et l'IDE préféré pour le développement Android. Il est disponible gratuitement pour les systèmes d'exploitation Windows, Mac et Linux..

Pour des instructions complètes sur l'installation d'Eclipse (y compris les versions prises en charge) et le SDK Android, voir le site Web du développeur Android..

Qu'est-ce qu'une classe intérieure??

La plupart des classes en Java sont des classes de niveau supérieur. Ces classes et les objets qu'elles définissent sont autonomes. Vous pouvez également créer des classes imbriquées afin d'encapsuler et de définir clairement les objets subordonnés qui importent uniquement dans le contexte de la classe externe. Les classes imbriquées sont appelées classes internes.

Les classes internes peuvent avoir toutes les fonctionnalités d'une classe standard, mais leur portée est limitée. Les classes internes ont un autre avantage: elles ont un accès complet à la classe dans laquelle elles sont imbriquées. Cette fonctionnalité rend les classes internes parfaitement adaptées à la mise en oeuvre de fonctionnalités d'adaptateur telles que les itérateurs..

Voici un exemple de classe de niveau supérieur avec deux classes internes:

 Classe publique Utilisateur // Champs utilisateur, y compris les variables de type LoginInfo et UserPreferences // Méthodes utilisateur diverses classe LoginInfo // Champs d'informations de connexion // Méthodes de connexion / déconnexion // Peut accéder aux champs / méthodes d'utilisateur classe Préférences // Utilisateur champs de préférence // Méthodes de préférences Get / Set // Réinitialiser la méthode de préférences // Peut accéder aux champs / méthodes de l'utilisateur 

Dans cet exemple, la classe User a deux classes internes: LoginInfo et Preferences. Bien que toutes les données et fonctionnalités liées à l'utilisateur puissent être définies dans la classe User, l'utilisation des classes internes pour compartimenter les fonctionnalités peut faciliter la lecture et la maintenance du code. Les classes internes LoginInfo et Preferences ont également accès aux champs et méthodes protégés / privés disponibles dans la classe User, qu'elles n'auraient peut-être pas autrement pour des raisons de sécurité, si elles étaient définies en tant que classes autonomes elles-mêmes..

Cependant, il est important de garder à l'esprit que les classes internes n'existent réellement que pour aider le développeur à organiser le code; le compilateur traite les classes internes comme toute autre classe, sauf que les classes internes ont une portée limitée et sont donc rattachées à la classe avec laquelle elles sont définies. Autrement dit, vous ne pourriez pas utiliser ni instancier les classes LoginInfo ou Preferences, sauf avec une instance de la classe User, mais les classes internes pourraient accéder à tous les champs ou méthodes disponibles dans la classe externe User, selon les besoins..

Utilisation de classes imbriquées statiques

Les classes imbriquées sont particulièrement utiles pour les classes imbriquées. Une classe interne statique définit un comportement qui n'est pas lié à une instance d'objet spécifique, mais s'applique à toutes les instances. Par exemple, nous pourrions ajouter une troisième classe imbriquée, cette fois statique, à la classe User pour contrôler les fonctionnalités liées au serveur:

 Classe publique User // Champs utilisateur, y compris les variables de type LoginInfo et UserPreferences // Méthodes utilisateur diverses classe LoginInfo  Classe statique publique ServerInfo  // Les informations de serveur s'appliquent à toutes les instances de User. 

Comme elle est publique, cette classe imbriquée statique peut être instanciée à l'aide de la nouvelle instruction suivante:

 User.ServerInfo sInfo = new User.ServerInfo (); 

La classe externe n'a pas besoin d'être instanciée pour effectuer cette instanciation, d'où l'utilisation du nom de classe. En tant que telle, une classe imbriquée statique, contrairement à une classe imbriquée non statique (alias classe intérieure), n'a pas accès aux membres de la classe externe - elles ne peuvent même pas être instanciées..

La puissance des classes intérieures anonymes

Android utilise des classes internes anonymes à bon escient. Les classes internes anonymes sont un raccourci de développeur permettant au développeur de créer, définir et utiliser un objet personnalisé dans une seule "ligne". Vous avez peut-être déjà vu des exemples d'utilisation d'une classe interne anonyme dans un exemple de code sans même vous en rendre compte..
Pour créer une classe interne anonyme, vous ne fournissez que le côté droit de la définition. Commencez par le nouveau mot-clé, suivi de la classe ou de l'interface que vous souhaitez étendre ou implémenter, suivi de la définition de la classe. Cela créera la classe et la retournera sous forme de valeur que vous pourrez ensuite utiliser pour appeler une méthode..
Lorsque nous utilisons une classe interne anonyme, l'objet créé ne se voit pas attribuer un nom (donc le terme anonyme). L’effet secondaire, bien sûr, est que l’objet n’est utilisé qu’une fois. Par exemple, il est courant d'utiliser une classe interne anonyme pour construire une version personnalisée d'un objet en tant que valeur de retour. Par exemple, ici nous étendons la classe Truck (en supposant que celle-ci soit définie ailleurs et comporte un champ appelé mpg et deux méthodes, start () et stop ():

 Truck getTruck () retourne un nouveau camion () int mpg = 3; void start () / * démarrer la mise en oeuvre * / void stop () / * arrêter la mise en oeuvre * /;  

Regardons maintenant des exemples pratiques de classes internes anonymes utilisées dans Android.

Utilisation d'une classe interne anonyme pour définir un auditeur

Les développeurs Android utilisent souvent des classes internes anonymes pour définir des écouteurs spécialisés, qui enregistrent des rappels pour un comportement spécifique lorsqu'un événement se produit. Par exemple, pour écouter les clics sur un contrôle View, le développeur doit appeler la méthode setOnClickListener (), qui prend un seul paramètre: un objet View.OnClickListener..
Les développeurs utilisent régulièrement la technique de la classe interne anonyme pour créer, définir et utiliser leur View.OnClickListener personnalisé, comme suit:

 Bouton aButton = (Bouton) findViewById (R.id.MyButton); aButton.setOnClickListener (new View.OnClickListener () public void onClick (Voir v) // L'utilisateur a cliqué sur mon bouton, faites quelque chose ici!); 

Utilisation d'une classe interne anonyme pour démarrer un fil

Regardons un autre exemple. Il est assez courant de définir une nouvelle classe Thread, de fournir l'implémentation de sa méthode run () et de démarrer ce thread en une fois:

 new Thread () public void run () doWorkHere ();  .début(); 

Utiliser une classe interne nommée

Utiliser des classes internes anonymes pour les auditeurs sous Android est si courant qu'il est pratiquement naturel de le faire. Pourquoi, alors, ne voudriez-vous pas les utiliser? Répondons à cela par un exemple hypothétique.
Disons que vous avez un écran avec 100 boutons (nous avons dit hypothétique, non?). Maintenant, disons que chaque bouton, quand on appuie dessus, fait le exactement la même chose. Dans ce cas, nous allons simplement écouter les clics et Toast le texte de l'objet View transmis (le texte affiché sur le bouton sur lequel l'utilisateur a cliqué):
Voici un pseudo-code pour le faire:

 Bouton [] boutons = getAllOneHundredButtonsAsArray (); for (bouton bouton: boutons) button.setOnClickListener (nouvelle View.OnClickListener () public void onClick (Voir v) showToast (v.getText ()););  

Court et élégant, alors qu'est-ce qui ne va pas? A chaque itération, un nouvel objet OnClickListener est instancié. Puisque chacun est exactement le même, il n'y a aucune bonne raison de créer 100 d'entre eux. Au lieu de cela, vous pouvez créer une seule classe interne nommée, l'instancier une fois, puis la transmettre à la méthode setOnClickListener (). Par exemple:

 La classe MyActivity étend Activity public void myMethod () gestionnaire MyClickHandler = new MyClickHandler (); Bouton [] boutons = getAllOneHundredButtonsAsArray (); for (bouton bouton: boutons) button.setOnClickListener (gestionnaire);  La classe MyClickHandler implémente View.OnClickListener annulation publique onClick (View v) showToast (((Button) v) .getText ());  

Si vous préférez l'anonymat, vous pouvez toujours affecter une classe interne anonyme à une variable et l'utiliser de la manière suivante:

 La classe MyActivity étend Activity public void myMethod () View.OnClickListener gestionnaire = new View.OnClickListener () public void onClick (Afficher v) showToast (((Button) v) .getText ()); ; Bouton [] boutons = getAllOneHundredButtonsAsArray (); for (bouton bouton: boutons) button.setOnClickListener (gestionnaire);  

La méthode vous appartient, mais gardez à l’esprit les problèmes de mémoire et de performances potentiels liés à l’instanciation d’un groupe d’objets..

Une note sur les nuances

Ce tutoriel est destiné à être un guide d'introduction aux classes internes en Java. Il existe des considérations de style et des nuances lorsqu’on utilise des classes internes de manières différentes et créatives. Même au-delà, vous pouvez explorer davantage pour en savoir plus sur les effets internes et les différences de performances marginales pouvant apparaître lorsque vous utilisez des classes imbriquées de différentes manières. Cependant, tout cela dépasse le cadre de ce tutoriel..

Une note rapide sur la terminologie

Bien que nous ayons essayé d’être cohérents avec la terminologie relative aux classes imbriquées et internes, la terminologie n’est pas toujours cohérente pour différentes ressources en ligne et hors connexion. Vous trouverez ci-dessous une liste de termes issus de la documentation Sun / Oracle en cours, ce qui en vaut le moins pour faire autorité sur Java:

  • Classe imbriquée: une classe définie dans une autre classe
  • Classe imbriquée statique: une classe statique définie dans une autre classe
  • Classe intérieure: une classe imbriquée non statique définie dans une autre classe
  • Classe intérieure locale: une classe définie dans une méthode
  • Classe intérieure anonyme: une classe sans nom définie dans une méthode

Confus? Vous pouvez utiliser les méthodes java.lang.Class nommées isLocalClass () et isAnonymous () sur les classes instanciées pour déterminer quelques-unes de ces propriétés. Une entrée de blog Oracle tente aussi de clarifier un peu la situation avec un joli diagramme de Venn.

Emballer

Le langage de programmation Java prend en charge les classes imbriquées, offrant au développeur une grande souplesse dans la définition des objets. Les classes internes peuvent être utilisées pour organiser les fonctionnalités des classes ou pour définir des comportements spécialisés qui obligeraient autrement le développeur à exposer des données de classe et des fonctionnalités qui ne devraient vraiment pas être exposées. Les classes internes statiques peuvent être utilisées pour définir des champs et des fonctionnalités qui s'appliquent à toutes les instances d'une classe. Enfin, les classes internes anonymes constituent un raccourci utile pour les développeurs souhaitant créer, définir et utiliser simultanément un objet personnalisé..