Archives Wild Code School
Java

Java 05 : Méthodes

Quête 11 sur 43

Dans cette quête, tu vas découvrir ce que sont les méthodes dans Java, comment les utiliser et comment en créer toi-même. En tant que développeur, tu as peut-être déjà entendu parler de fonctions. Une méthode est une fonction, mais dans un contexte particulier (POO).

Garde en tête que ce que tu vas apprendre ici n'est pas propre à Java, et se retrouve aussi dans beaucoup d'autres langages.

Objectifs

  • Savoir utiliser une méthode,
  • Créer ses propres méthodes,

Utiliser une méthode.

En fait, tu en as déjà utilisé :)

Tu te rappelles de System.out.println ? Ou Arrays.toString ? Arrays.sort ? Ce sont des méthodes : des fonctionnalités pré-écrites pour permettre à ton programme principal -- main, une autre méthode ;) -- de faire son travail.

En programmation, tu peux avoir besoin à plusieurs reprises d'une même fonctionnalité. Tu verras que cela te sera plus souvent nécessaire que tu ne l'imagines. Nous allons explorer un exemple : ajouter un élément à un tableau.

Considérons ce tableau Java comme exemple :

java
String[] moviesArray = {
  "Raiders of the Lost Ark",
  "Indiana Jones and the Temple of Doom",
  "Indiana Jones and the Last Crusade",
  "Indiana Jones and the Kingdom of he Crystal Skulls"
};

On dispose ainsi du tableau contenant la liste des aventures de notre archéologue. Tu peux le voir avec une boucle qui affiche le contenu du tableau dans la console :

java
for (String movie : moviesArray) {
    System.out.println(movie);
}

Sauf que, si Indy venait à rempiler chez les Atlantes ou faire des fouilles dans les données personnelles Facebook, on voudrait rajouter un élément au tableau. Cela nécessiterait de créer un nouveau tableau, plus grand, d'y copier index par index les données existantes et de rajouter enfin le nom du nouveau film :

java
String[] moviesArray2 = new String[moviesArray.length + 2];

for(int i = 0; i < moviesArray.length; i++) {
    moviesArray2[i] = moviesArray[i];
}

int lastPreviousIndex = moviesArray.length - 1;

moviesArray2[lastPreviousIndex + 1] = "Indiana Jones and the Fate of Atlantis";
moviesArray2[lastPreviousIndex + 2] = "Indiana Jones and Facebook's Personal Data";

Le nouveau tableau moviesArray2 contient tous les anciens films, complété des 2 nouvelles aventures d'Indy. Chaque fois que tu voudras ajouter un film, ou de manière plus générique, ajouter un élément à un tableau, tu devras effectuer cette petite boucle, en dupliquant le code.

Pour cet exemple, très simpliste, tu te dis que copier-coller une simple boucle, ce n'est pas méchant. Sauf qu'il existe déjà nativement quelque chose dans Java, qui te permet d'obtenir le même résultat beaucoup plus simplement :

java
String[] moviesArray2 = Arrays.copyOf(moviesArray, moviesArray.length + 2);

int lastPreviousIndex = moviesArray.length - 1;

moviesArray2[lastPreviousIndex + 1] = "Indiana Jones and the Fate of Atlantis";
moviesArray2[lastPreviousIndex + 2] = "Indiana Jones and Facebook's Personal Data";

La méthode Arrays.copyOf, suivie de 2 parenthèses () à l’intérieur desquelles tu dois préciser le tableau à copier et sa nouvelle taille. Ce sont les arguments de la méthode. Nous en reparlerons plus tard.

Chaque classe Java dispose d'un grand nombre de méthodes dont tu peux user et abuser. Il suffit de regarder la classe String. Certaines sont tellement courantes et utiles que tu les maîtriseras parfaitement. Évidemment, il y en a trop pour toutes se les rentrer dans le crâne.

Attention, le nom des méthodes est sensible à la casse ! Si tu fais appel à CopyOf(), Java ne comprendra pas que tu lui demandes copyOf();

↗
Documentation officielle

Voici ton nouveau meilleur ami, la documentation officielle de l'API Java ! C'est grâce à elle que tu peux savoir exactement comment utiliser telle ou telle méthode.

docs.oracle.com

Créer ses propres méthodes

Comme vu précédemment, une méthode effectue un ensemble prédéterminé de code et peut être appelée quand tu le désires. Cela te permettra d’exécuter à plusieurs reprises le même algorithme sans jamais faire de copier-coller. Car tu le découvriras vite, moins tu fais de copier-coller, plus c'est le signe que ton code est propre, bien structuré et cohérent.

Le fait de se répéter le moins possible dans son code, c'est le principe du code DRY ( Don't Repeat Yourself). En programmation, tu découvriras qu'il y a de nombreux "courants philosophiques", prônant différentes approches pour produire un code propre, fonctionnel et optimisé. DRY en est un.

Tu l'auras compris, les classes du runtime Java contiennent déjà des centaines de méthodes intégrées que tu peux utiliser au quotidien dans ton application. Mais en tant que développeur, tu seras également très souvent amené à créer tes propres méthodes.

Créer une méthode est un peu comme écrire une recette de cuisine : en partant d'ingrédients au départ, on effectue des actions -- les étapes de la recette -- pour transformer les ingrédients en un résultat final. Pour le dire en images :

  • blender est le nom de la fonction, et quand une fonction appartient à une classe, on parle de méthode.

  • milk, banana et kiwi sont les paramètres de la méthode, et pour chaque paramètre, le type est précisé comme tu le ferais pour déclarer une variable -- Liquid pour milk, Fruit pour banana et kiwi. Note que les différents paramètres sont séparés par des ,.

java
Smoothie blender(Liquid liquid, Fruit[] fruits) {
    // mix the fruits with the liquid
     and return the result
}

Ok, mais tu nous parles de "paramètres" alors que sur l'image c'est marqué "arguments" ?!?

C'est juste : les 2 mots servent à parler de la même chose, mais à des moments différents. Le paramètre est le nom de l'ingrédient lorsque tu définis ta recette. L'argument est la valeur de l'ingrédient au moment où tu l'utilises. Cela peut te sembler subtil pour l'instant, mais à force d'utiliser des méthodes, tu comprendras la différence entre les deux mots. Pour l'instant, accepte-les comme des synonymes.

Attention! L'image peut laisser croire que les fruits sont forcément des bananes ou des kiwis : ce n'est qu'une image :)

Une version plus "réaliste" du blender pourrait ressembler à ça :

java
// define the method
Smoothie blender(Liquid liquid, Fruit fruit1, Fruit fruit2) {
    // mix the fruits with the liquid
    // return the result
}

// blender is defined, we can use it now

// first initialize arguments
Liquid greekYogurt = new Liquid("greekYogurt");
Fruit strawberry = new Fruit("strawberry");
Fruit raspberry = new Fruit("raspberry");

// then give the arguments to the method, and get the result
Smoothie mySmoothie = blender(greekYogurt, strawberry, raspberry);

Comme tu le vois dans ce code, au lieu de milk, banana et kiwi, j'ai utilisé pour les paramètres de blender les noms liquid, fruit1 et fruit2 . Cela te montre qu'avec la même méthode, je peux utiliser autre chose que du lait, de la banane et du kiwi pour faire mon smoothie, tant que que je mets dans mon blender des ingrédients de type Liquid et Fruit.

Quant au nom de la méthode, tu es libre de l'appeler comme tu veux, du moment que tu respectes les contraintes qu'impose Java, qui sont les mêmes que pour les variables. Pour rappel, un nom de méthode :

  • ne peut pas commencer par une valeur numérique,

  • ne doit pas contenir de caractères interdits (@, -, ...),

  • doit être unique et ne pas être un nom réservé (comme class() ou int() par exemple).

Tu dois également penser à la propreté et à la maintenabilité du code. Comme pour nommer ses variables, il est important de bien nommer ses méthodes. Une classe remplie de toto();, tata(); et de doSomething(); et getStuff(); ne sera pas très facile à comprendre.

Utilise des noms cohérents, représentatifs de ce que cela fait et utilisant la syntaxe camelCase qui est préconisée. Comme, par exemple: getTotalPrice(double price, double taxeRate) ou filterSubscribedUsers(users)

Assez de blabla, passons à l'action ! Créons une méthode qui exécute le coup gagnant au chifoumi :

java
class Chifoumi {
    public static String counterAttack(String attack) {
        if (attack.equals("pierre")) {
            return "feuille";
        }
        if (attack.equals("feuille")) {
            return "ciseaux";
        }
        // if (attack.equals("ciseaux"))
        return "pierre";
    }

    public static void main(String[] args) {
        System.out.println("Indy joue pierre");
        System.out.println("Je joue " + counterAttack("pierre"));

        System.out.println("Indy joue feuille");
        System.out.println("Je joue " + counterAttack("feuille"));

        System.out.println("Indy joue ciseaux");
        System.out.println("Je joue " + counterAttack("ciseaux"));
    }
}

La méthode counterAttack prend en entrée un paramètre de type String et renvoie une String qui est notre coup gagnant. La méthode main fait plusieurs appels à counterAttack pour simuler une partie entre Indy et l'ordinateur.

Note: void sur la méthode main signifie pas de type de retour.

Tu peux copier-coller ce code, l'exécuter et faire des expériences avec ;)

Challenge

Un message codé pour Indy

Entre deux smoothies et parties de chifoumi, Indiana Jones, le célèbre professeur / archéologue / aventurier, a récupéré trois papyrus antiques contenant chacun un message codé ! Heureusement, il a également découvert la manière de les déchiffrer, mais c'est un peu compliqué de le faire à la main.

Il te donne alors les instructions pour que tu développes un programme permettant d'automatiser le processus. Cela pourra être d'autant plus utile s'il rencontre à nouveau ce système de chiffrement plus tard.

Voici comment procéder :

  • Calcule la longueur de la chaîne et divise-la par 2, tu obtiendras ainsi le "chiffre-clé".
  • Récupère ensuite la sous-chaîne de la longueur du chiffre-clé, en commençant à partir du 6ème caractère.
  • Remplace les chaînes '@#?' par un espace.
  • Pour finir, inverse la chaîne de caractères.

Pour ceci, crée une classe Decipherer (c'est-à-dire un fichier Decipherer.java) où tu dois définir ta méthode.

Appelle ensuite ta méthode dans une méthode main sur chacun des messages suivants, et poste le code Java que tu as écrit, ainsi que les textes déchiffrés sur un Gist.

  • message 1 : 0@sn9sirppa@#?ia'jgtvryko1
  • message 2 : q8e?wsellecif@#?sel@#?setuotpazdsy0*b9+mw@x1vj
  • message 3 : aopi?sedohtém@#?sedhtmg+p9l!

Ressources

Critères de validation

  • Le fichier Decipherer.java est disponible depuis un lien Gist,
  • Les bons types sont appliqués au paramètre et au retour,
  • Le mot clé return est utilisé dans la méthode pour renvoyer le résultat,
  • L'affichage du résultat se fait bien à l’extérieur de la méthode et non directement dedans,
  • Le message secret est bien déchiffré. Il faudra appeler la méthode trois fois, une fois pour chaque message, pour confirmer que tout fonctionne correctement.

Ressources partagées sur cette quête