Activité Méthode d'instance

Objectifs

À la fin de ce travail, vous devez :

  1. Connaître les notions de méthode de classe (méthode statique) et de méthode d’instance.
  2. Connaître la syntaxe de la définition d’une méthode d’instance en Java.
  3. Connaître le mot clé this et savoir ce qu’il représente.
  4. Être capable de distinguer l’appel d’une méthode de classe et l’appel d’une méthode d’instance.

Consigne

Vous êtes invité à lire et à prendre connaissance de l’activité en lisant attentivement le contenu de cette page en totalité et à réaliser les tâches décrites ci-après.

Il s’agit d’une activité d’apprentissage et non d’un tutoriel. Vous devez réaliser les tâches en ayant en tête les objectifs à atteindre.

Demandez de l’aide en cas de besoin, mais essayez d’abord par vous-même et respectez toujours le code d’honneur !

Résultat attendu

Un projet Maven qui réalise les fonctionnalités demandées.

Ressources

Logiciel :

  • Maven
  • Visual Studio Code

Documents :

Situation

Vous venez d’être intégré à une équipe chargée du développement d’un logiciel de gestion de bibliothèque. On vous confie la tâche d’améliorer un programme qui affiche le catalogue des livres.

Mise en route

Lancez la machine virtuelle de développement avec Vagrant. Lancez Visual Studio Code, connectez-vous à la machine virtuelle et ouvrez la fenêtre de terminal intégré.

Rendez-vous dans le répertoire de projets (~/projects) et lancez la commande suivante :

1
git clone https://gitlab.epai-ict.ch/m226/instance-method.git --single-branch

Déplacez-vous dans le répertoire instance-method et lancer la commande code -r . pour ouvrir le projet dans la fenêtre courante.

Toujours, dans la fenêtre de terminal intégré lancez les commandes suivantes pour créer la base de données SQL et charger des données, si cela n’est pas déjà fait ou si vous avez un doute.

1
2
3
mysql -u root -pepai123 -e 'drop database book_catalog;' 2> /dev/null
mysql -u root -pepai123 < data/book-catalog.sql 
mysql -u root -pepai123 < data/data-dump.sql 

Dans le projet, vous trouvez trois classes : App, Book et BookOperations.

La première App contient un programme qui permet d’afficher le catalogue de livre dans la sortie standard.

La deuxième, Book, définit une structure de données qui permet de représenter un livre. Cette structure de données est utilisée à la ligne 55 de la classe App. L’instruction de cette ligne est exécutée à chaque itération de la boucle. Puisqu’il s’agit d’une affectation, elle s’exécute en deux temps :

  1. Évaluation de l’expression new Book(...).
  2. Stockage de la valeur de l’expression dans la variable b.

L’opérateur new nous apprend que l’expression est une instanciation (création d’un objet). Une telle expression est évaluée en trois temps :

  1. Allocation dans le tas d’une zone de mémoire suffisante pour stocker les valeurs des variables membres de la classe Book.
  2. Appel du constructeur correspondant aux paramètres effectifs pour initialiser chacune des variables membres.
  3. Renvoie de l’adresse de la zone de mémoire (référence).

Après l’exécution de l’instruction, la variable b contient donc une référence à un nouvel objet de type Book.

Enfin, la troisième classe, BookOperations, contient des méthodes statiques qui permettent de manipuler les données d’un objet de type Book. Chacune de ces méthodes prend un paramètre de type Book qui représente l’objet particulier dont on veut manipuler les données.

Si vous observer la classe App, vous pouvez constater que les variables membres de la classe Book ne sont jamais accédé directement, mais toujours à travers l’appel de l’une des méthodes de la classe BookOperations. C’est un point important sur lequel nous reviendrons un peu plus tard.

Nous pouvons voir qu’une classe peut être utilisée pour réaliser une structure de donnée ou pour regrouper un ensemble de méthodes (procédures et fonctions).

Avant de poursuivre, exécuter le programme pour vous assurer qu’il fonctionne correctement.

Tâches

Combiner structure de données et méthodes

Comme nous l’avons dit, une classe peut être utilisée pour réaliser une structure de donnée ou pour regrouper un ensemble de méthodes, mais une même classe peut être utilisée à la fois pour l’un et l’autre.

Copiez les méthodes de la classe BookOperations et copiez-les dans la classe Book en dessous des variables membres. Lorsque cela est fait, supprimez la classe BookOperations et corrigez les erreurs de syntaxe dans la classe App, puis exécutez le programme pour vérifier qu’il fonctionne toujours correctement.

Cacher les variables membres

En déplaçant les méthodes dans la classe Book, les méthodes et les variables membres se trouvent maintenant dans la même classe. Comme par principe, les variables membres ne sont jamais accédées directement, nous pouvons maintenant en limiter l’accès au code qui se trouve à l’intérieur de la classe. Puisque cela revient à cacher ou à dissimuler les détails de la structure de données, on parle de dissimulation d’information (information hiding).

Pour cela, remplacez le modificateur public des variables membres par le modificateur private. Les variables membres sont maintenant invisibles depuis l’extérieur de la classe.

Avant de poursuivre, exécutez le programme pour vérifier qu’il fonctionne toujours correctement.

Remplacer les méthodes de classe par des méthodes d’instance

Jusqu’à présent, nous n’avons créé que des méthodes statiques que l’on appelle, de manière plus générale, méthode de classe. En effet, pour appeler une telle méthode, on utilise le nom de la classe suivi d’un point, du nom de la méthode et de la liste des paramètres effectifs entre parenthèses (éventuellement vide). Une méthode d’instance est une méthode que l’on appelle sur une instance de la classe référencée par une expression, le plus souvent une variable.

En d’autres termes, si ce qui se trouve devant le point est le nom d’une classe, alors il s’agit d’un appel à une méthode de classe (méthode statique). En revanche, si ce qui se trouve devant le point est une expression (souvent une variable), alors il s’agit d’un appel à une méthode d’instance. Dans le cas d’une méthode de classe, on dit que la méthode est appelée ou invoquée sur la classe et dans le cas d’une méthode d’instance, on dit que la méthode est appelée ou invoquée sur l’objet.

La définition d’une méthode d’instance s’écrit de la même manière que celle d’une méthode de classe, mais sans le modificateur static.

Modfiez les méthodes de la classe Book pour en faire des méthodes d’instance, puis corrigez les erreurs de syntaxe dans la classe App et vérifiez que le programme fonctionne toujours.

Utiliser le mot clé this

Si vous avez réaliser votre travail correctement, le code de la méthode printBook devrait ressembler à celui présenté ci-dessous.

1
2
3
4
5
6
7
8
9
10
11
12
13
    public static void printBook(Book b) {
        System.out.println("-------------------------------");

        System.out.printf(
            "ID:        %d%nTitle:     %s%nYear:      %s%nPublisher: %s%nISBN:      %s%nAuthor:    %s%nNumber of pages: %d%n", 
            b.getId(b), 
            b.getTitle(b), 
            b.getYear(b), 
            b.getPublisher(b), 
            b.getIsbn(b), 
            b.getAuthor(b), 
            b.getNumOfPages(b));
    }

En observant ce code, on peut constater que pour chacune des méthodes, le premier paramètre est une référence à l’objet sur lequel la méthode est invoquée. C’est tout à fait normal puisque chacune de ces méthodes représente une opération que l’on peut effectuer sur les données d’un objet, un paramètre semble être la bonne manière de passer l’objet à la méthode.

Toutefois, une méthode d’instance d’une classe représente toujours une opération qui peut être effectuée sur les données d’une instance de cette classe. De fait, une méthode d’instance a toujours au moins un paramètre. Ce paramètre représente l’objet sur lequel l’opération doit être effectuée et sa valeur est toujours l’objet sur lequel la méthode est invoquée (invoquer une méthode sur un objet est synonyme d’effectuer une opération sur les données de cet objet). De fait, dans les langages de programmation orientée objet, il n’est généralement pas nécessaire ni de déclarer ni de passer une valeur à ce paramètre, qui est remplacé par un mot clé du langage.

En Java ce mot clé est this. Dans une méthode d’instance, le mot clé this représente l’objet sur lequel la méthode a été invoquée. Par exemple, lorsque l’on appelle méthode getId sur l’objet référencé par la variable b (b.getId()), à l’intérieur de cette méthode, le mot clé this représente le même objet que la variable b et this.id permet d’accéder à la variable membre id de cet objet.

Vous pouvez donc modifier les méthodes de la classe Book en supprimant le premier paramètre de chacune d’elles (Book b) et en remplaçant les occurrences de ce paramètre par le mot clé this. Corrigez ensuite les erreurs de syntaxe de la classe App, et exécutez le programme pour vous assurer qu’il fonctionnent encore.

Pour conclure

En observant la classe Book, nous pouvons voir que celle-ci définit à la fois une structure de données (les variables membres) et un ensemble d’opérations (méthodes d’instance) qui peuvent être effectuées sur les instances de cette structure de données. Il apparaît donc que dans un langage orienté objet, une classe est une construction du langage qui permet de définir un type de données.

Alors que les classes Book et BookOperations constitue l’implémentation d’un type de données en programmation procédurale, la classe Book telle qu’elle se pésente à la fin de cette activité est l’implémentation d’un type de données en programmation orientée objet.

Une variable est l’abstraction d’une valeur stockée dans la mémoire. Un sous-programme (méthode) est l’abstraction d’une séquence d’instructions. Un type de données est l’abstraction d’une structure de données, représentée par des variables membres, et d’un ensemble d’opérations, représentées par des méthodes d’instance.

La programmation orientée objet consiste essentiellement à définir des types de données.