CodeGym/Blog Java/Random-FR/Méthodes en Java
Auteur
John Selawsky
Senior Java Developer and Tutor at LearningTree

Méthodes en Java

Publié dans le groupe Random-FR
membres
Rebonjour! Dans la dernière leçon, nous nous sommes familiarisés avec les classes et les constructeurs et avons appris à créer les nôtres. Aujourd'hui, nous allons mieux nous familiariser avec les méthodes Java, une partie essentielle des classes. Une méthode en Java est un ensemble de commandes qui vous permettent d'effectuer une opération spécifique dans un programme. En d'autres termes, une méthode est une fonction ; quelque chose que votre classe est capable de faire. Dans d'autres langages de programmation, les méthodes sont souvent appelées "fonctions", mais en Java, le mot "méthode" est plus courant. :) Si vous vous souvenez, dans la dernière leçon, nous avons créé des méthodes simples pour une classe Cat , afin que nos chats puissent dire miaou et sauter :
public class Cat {

    String name;
    int age;

    public void sayMeow() {
        System.out.println("Meow!");
    }

    public void jump() {
        System.out.println("Pounce!");
    }

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";

        smudge.sayMeow();
        smudge.jump();
    }
}
sayMeow() et jump() sont des méthodes de notre classe. Et l'exécution de ces méthodes donne la sortie de console suivante :
Meow!
Pounce!
Nos méthodes sont assez simples : elles envoient simplement du texte à la console. Mais en Java, les méthodes ont une tâche importante : elles effectuent des actions sur les données d'un objet. Ils modifient les données de l'objet, le transforment, l'affichent et font d'autres choses avec. Nos méthodes actuelles ne font rien avec les données de l'objet Cat . Prenons un exemple plus illustratif :
public class Truck {

    int length;
    int width;
    int height;
    int weight;

    public int getVolume() {
        int volume = length * width * height;
        return volume;
    }
}
Par exemple, nous avons ici une classe représentant un Truck . Le semi-remorque a une longueur, une largeur, une hauteur et un poids (dont nous aurons besoin plus tard). Dans la méthode getVolume() , nous effectuons des calculs, convertissant les données de notre objet en un nombre représentant son volume (nous multiplions la longueur, la largeur et la hauteur). Ce nombre sera le résultat de la méthode. Notez que la déclaration de la méthode est écrite sous la forme public int getVolume . Cela signifie que cette méthode doit renvoyer un int . Nous avons calculé la valeur de retour de la méthode, et maintenant nous devons la renvoyer au programme qui a appelé notre méthode. Pour renvoyer le résultat d'une méthode en Java, nous utilisons le mot-clé return. volume de retour ;

Paramètres de méthode Java

Nous pouvons passer des valeurs appelées "arguments" à une méthode lors de son appel. La déclaration d'une méthode inclut une liste de variables qui nous indique le type et l'ordre des variables que la méthode peut accepter. Cette liste s'appelle les "paramètres de la méthode". La méthode getVolume() de notre classe Truck ne définit actuellement aucun paramètre, alors essayons d'étendre notre exemple de camion. Créez une nouvelle classe appelée BridgeOfficer . Il s'agit d'un policier en service à un pont, qui vérifie tous les camions qui passent pour voir si leur charge dépasse le poids autorisé.
public class BridgeOfficer {

    int maxWeight;

    public BridgeOfficer(int normalWeight) {
        this.maxWeight = normalWeight;
    }

    public boolean checkTruck(Truck truck) {
        if (truck.weight > maxWeight) {
            return false;
        } else {
            return true;
        }
    }
}
La méthode checkTruck accepte un argument, un objet Truck , et détermine si l'agent autorise ou non le camion sur le pont. À l'intérieur de la méthode, la logique est assez simple : si le poids du camion dépasse le maximum autorisé, la méthode renvoie false . Il va falloir trouver une autre route :( Si le poids est inférieur ou égal au maximum, ça peut passer, et la méthode retourne true. Si vous ne comprenez pas encore parfaitement les expressions "retour" ou "la méthode renvoie une valeur", faisons une pause dans la programmation et considérons-les à l'aide d'un exemple simple tiré de la vie réelle. :) Disons que vous tombez malade et restez à la maison pendant quelques jours. Vous vous présentez au service comptabilité avec votre certificat médical, car les congés de maladie sont censés être payés. Si nous comparons cette situation avec des méthodes, alors le comptable a un paySickLeave()méthode. Vous passez une note du médecin comme argument à cette méthode (sans elle, la méthode ne fonctionnera pas et vous ne serez pas payé !). Ensuite, les calculs nécessaires sont effectués à l'intérieur de la méthode à l'aide de votre note (le comptable l'utilise pour calculer combien l'entreprise doit vous payer), et le résultat de votre travail (une somme d'argent) vous est restitué. Notre programme fonctionne de manière similaire. Il appelle une méthode, lui transmet des données et reçoit finalement un résultat. Voici la méthode main() de notre programme BridgeOfficer :
public static void main(String[] args) {
    Truck first = new Truck();
    first.weight = 10000;
    Truck second = new Truck();
    second.weight = 20000;

    BridgeOfficer officer = new BridgeOfficer(15000);
    System.out.println("Truck 1! Can I go, officer?");
    boolean canFirstTruckGo = officer.checkTruck(first);
    System.out.println(canFirstTruckGo);

    System.out.println();

    System.out.println("Truck 2! And can I?");
    boolean canSecondTruckGo = officer.checkTruck(second);
    System.out.println(canSecondTruckGo);
}
Nous créons deux camions avec des chargements de 10 000 et 20 000. Et le pont où travaille l'officier a un poids maximum de 15 000. Le programme appelle la méthode officer.checkTruck(first) . La méthode calcule tout puis renvoie true , que le programme enregistre ensuite dans la variable booléenne canFirstTruckGo . Maintenant, vous pouvez en faire ce que vous voulez (tout comme vous pouvez le faire avec l'argent que le comptable vous a donné). Au bout du compte, le code
boolean canFirstTruckGo = officer.checkTruck(first);
se résume à
boolean canFirstTruckGo =  true;
Voici un point très important : l' instruction return ne se contente pas de renvoyer la valeur de retour de la méthode, elle arrête également l'exécution de la méthode ! Tout code qui vient après l' instruction return ne sera pas exécuté !
public boolean checkTruck(Truck truck) {

    if (truck.weight > maxWeight) {
        return false;
        System.out.println("Turn around, you're overweight!");
    } else {
        return true;
        System.out.println("Everything looks good, go ahead!");
    }
}
Les commentaires de l'agent ne seront pas affichés, car la méthode a déjà renvoyé un résultat et s'est terminée ! Le programme retourne à l'endroit où la méthode a été appelée. Vous n'avez pas à faire attention à cela : le compilateur Java est suffisamment intelligent pour générer une erreur lorsque vous essayez d'écrire du code après une instruction de retour .

Avengers : guerre des paramètres

Il y a des situations où nous voudrons plusieurs façons d'appeler une méthode. Pourquoi ne pas créer notre propre intelligence artificielle ? Amazon a Alexa, Apple a Siri, alors pourquoi ne devrions-nous pas en avoir un ? :) Dans le film Iron Man, Tony Stark crée sa propre incroyable intelligence artificielle, Jarvis. Rendons hommage à ce personnage génial et nommons notre IA en son honneur. :) La première chose que nous devons faire est d'apprendre à Jarvis à dire bonjour aux personnes qui entrent dans la pièce (ce serait bizarre si un intellect aussi incroyable se révélait impoli).
public class Jarvis {

    public void sayHi(String name) {
        System.out.println("Good evening, " + name + ". How are you?");
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
    }
}
Sortie console :
Good evening, Tony Stark. How are you?
Très bien! Jarvis est maintenant en mesure d'accueillir des invités. Bien sûr, le plus souvent, ce sera son maître, Tony Stark. Et s'il ne vient pas seul ! Notre méthode sayHi() n'accepte qu'un seul argument. Ainsi, il ne peut saluer qu'une seule personne entrant dans la pièce et ignorera l'autre. Pas très poli, n'est-ce pas ? :/

Surcharge de méthode Java

Dans ce cas, on peut résoudre le problème en écrivant simplement 2 méthodes avec le même nom, mais des paramètres différents :
public class Jarvis {

    public void sayHi(String firstGuest) {
        System.out.println("Good evening, " + firstGuest + ". How are you?");
    }

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
    }
}
C'est ce qu'on appelle la surcharge de méthode. La surcharge de méthodes permet à notre programme d'être plus flexible et de s'adapter à différentes façons de travailler. Passons en revue son fonctionnement :
public class Jarvis {

    public void sayHi(String firstGuest) {
        System.out.println("Good evening, " + firstGuest + ". How are you?");
    }

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
        jarvis.sayHi("Tony Stark", "Captain America");
    }
}
Sortie console :
Good evening, Tony Stark. How are you?
Good evening, Tony Stark and Captain America. How are you?
Excellent, les deux versions ont fonctionné. :) Mais nous n'avons pas résolu le problème ! Et s'il y a trois invités ? Nous pourrions, bien sûr, surcharger à nouveau la méthode sayHi() , afin qu'elle accepte trois noms d'invités. Mais il pourrait y en avoir 4 ou 5. Jusqu'à l'infini. N'y a-t-il pas une meilleure façon d'apprendre à Jarvis à gérer n'importe quel nombre de noms, sans surcharger la méthode sayHi() un million de fois ? :/ Bien sûr que oui ! Si ce n'était pas le cas, pensez-vous que Java serait le langage de programmation le plus populaire au monde ? ;)
public void sayHi(String...names) {

    for (String name: names) {
        System.out.println("Good evening, " + name + ". How are you?");
    }
}
Lorsque ( String... names ) est utilisé comme paramètre, cela indique qu'une collection de Strings sera transmise à la méthode. Nous n'avons pas besoin de spécifier à l'avance combien il y en aura, donc maintenant notre méthode est beaucoup plus flexible :
public class Jarvis {

    public void sayHi(String...names) {
        for (String name: names) {
            System.out.println("Good evening, " + name + ". How are you?");
        }
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
    }
}
Sortie console :
Good evening, Tony Stark. How are you?
Good evening, Captain America. How are you?
Good evening, Black Widow. How are you?
Good evening, Hulk. How are you?
Certains codes ici ne vous seront pas familiers, mais ne vous inquiétez pas. C'est simple à la base : la méthode prend tour à tour chaque nom et salue chaque invité ! De plus, cela fonctionnera avec n'importe quel nombre de chaînes passées! Deux, dix, voire mille, la méthode fonctionnera correctement avec n'importe quel nombre d'invités. Bien plus pratique que de surcharger la méthode pour toutes les possibilités, vous ne pensez pas ? :) Voici un autre point important : l'ordre des arguments compte ! Disons que notre méthode prend une chaîne et un nombre :
public class Person {

    public static void sayYourAge(String greeting, int age) {
        System.out.println(greeting + " " + age);
    }

    public static void main(String[] args) {
        sayYourAge("My age is ", 33);
        sayYourAge(33, "My age is "); // Error!
    }
}
Si la méthode sayYourAge de la classe Person prend une chaîne et un nombre comme entrées, alors le programme doit les passer dans cet ordre spécifique ! Si on les passe dans un ordre différent, le compilateur générera une erreur et la personne ne pourra pas dire son âge. Au fait, les constructeurs, dont nous avons parlé dans la dernière leçon, sont aussi des méthodes ! Vous pouvez également les surcharger (c'est-à-dire créer plusieurs constructeurs avec différents ensembles de paramètres) et l'ordre des arguments passés est également fondamental pour eux. Ce sont de vraies méthodes ! :)

Encore une fois concernant les paramètres

Oui, désolé, nous n'en avons pas encore fini avec eux. :) Le sujet que nous allons étudier maintenant est très important. Il y a 90 % de chances que vous soyez interrogé à ce sujet à chaque entretien futur ! Parlons du passage d'arguments aux méthodes. Prenons un exemple simple :
public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        currentYear = currentYear-10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2018;

        System.out.println("What year is it?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("How about now?");
        System.out.println(currentYear);
    }
}
La machine à voyager dans le temps a deux méthodes. Ils prennent tous deux le nombre représentant l'année en cours comme entrée et augmentent ou diminuent sa valeur (selon que nous voulons aller dans le passé ou dans le futur). Mais, comme vous pouvez le voir sur la sortie de la console, la méthode ne fonctionne pas ! Sortie console :
What year is it?
2018
How about now?
2018
Nous avons passé la variable currentYear à la méthode goToPast() , mais sa valeur n'a pas changé. Nous étions en 2018, et ici nous sommes restés. Mais pourquoi? :/ Parce que les primitives en Java sont passées aux méthodes par valeur. Qu'est-ce que cela signifie? Lorsque nous appelons la méthode goToPast() et que nous lui transmettons la variable int currentYear (=2018) , la méthode n'obtient pas la variable currentYear elle-même, mais plutôt une copie de celle-ci. Bien sûr, la valeur de cette copie est également 2018, mais toute modification apportée à la copie n'affecte en rien notre variable originale currentYear ! Rendons notre code plus explicite et regardons ce qui se passe avec currentYear :
public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        System.out.println("The goToPast method has started running!");
        System.out.println("currentYear inside the goToPast method (at the beginning) = " + currentYear);
        currentYear = currentYear-10;
        System.out.println("currentYear inside the goToPast method (at the end) = " + currentYear);
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2018;

        System.out.println("What was the year when the program started?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("And what year is it now?");
        System.out.println(currentYear);
    }
}
Sortie console :
What was the year when the program started?
2018
The goToPast method has started running!
currentYear inside the goToPast method (at the beginning) = 2018
currentYear inside the goToPast method (at the end) = 2008
And what year is it now?
2018
Cela montre clairement que la variable passée à la méthode goToPast() n'est qu'une copie de currentYear . Et changer la copie n'affecte pas la valeur "d'origine". "Passer par référence" signifie exactement le contraire. Entraînons-nous sur les chats ! Je veux dire, voyons à quoi ressemble le passage par référence en utilisant un exemple de chat. :)
public class Cat {

    int age;

    public Cat(int age) {
        this.age = age;
    }
}
Maintenant, avec l'aide de notre machine à voyager dans le temps, nous enverrons Smudge , le premier chat voyageant dans le temps, dans le passé et le futur ! Modifions la classe TimeMachine pour qu'elle fonctionne avec les objets Cat ;
public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat.age -= 10;
    }
}
Maintenant, les méthodes ne changent pas seulement le nombre passé. Au lieu de cela, ils modifient le champ d'âge de ce chat spécifique . Vous vous souviendrez que cela ne fonctionnait pas pour nous avec les primitives, car le nombre d'origine n'a pas changé. Voyons ce qui va se passer !
public static void main(String[] args) {

    TimeMachine timeMachine = new TimeMachine();
    Cat smudge = new Cat(5);

    System.out.println("How old was Smudge when the program started?");
    System.out.println(smudge.age);

    timeMachine.goToFuture(smudge);
    System.out.println("How about now?");
    System.out.println(smudge.age);

    System.out.println("Holy smokes! Smudge has aged 10 years! Back up quickly!");
    timeMachine.goToPast(smudge);
    System.out.println("Did it work? Have we returned the cat to its original age?");
    System.out.println(smudge.age);
}
Sortie console :
How old was Smudge when the program started running?
5
How about now?
15
Holy smokes! Smudge has aged 10 years! Back up quickly!
Did it work? Have we returned the cat to its original age?
5
Ouah! Maintenant, la méthode a fait quelque chose de différent : notre chat a considérablement vieilli, mais il est redevenu jeune ! :) Essayons de comprendre pourquoi. Contrairement à l'exemple avec les primitives, lorsque des objets sont passés à une méthode, ils sont passés par référence. Une référence à l' objet de bavure d'origine a été transmise à la méthode changeAge() . Ainsi, lorsque nous modifions smudge.age dans la méthode, nous référençons la même zone de mémoire où notre objet est stocké. C'est une référence au même Smudge que nous avons créé initialement. C'est ce qu'on appelle "passer par référence" ! Cependant, tout ce qui a des références n'est pas si facile. :) Essayons de changer notre exemple :
public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat = new Cat(cat.age);
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat = new Cat(cat.age);
        cat.age -= 10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        Cat smudge = new Cat(5);

        System.out.println("How old was Smudge when the program started?");
        System.out.println(smudge.age);

        timeMachine.goToFuture(smudge);
        System.out.println ("Smudge went to the future! Has his age changed?");
        System.out.println(smudge.age);

        System.out.println ("And if you try going back?");
        timeMachine.goToPast(smudge);
        System.out.println(smudge.age);
    }
}
Sortie console :
How old was Smudge when the program started running?
5
Smudge went to the future! Has his age changed?
5
And if you try going back?
5
Ça ne marche plus ! О_О Découvrons ce qui s'est passé. :) Cela a tout à voir avec les méthodes goToPast / goToFuture et le fonctionnement des références. Maintenant, votre attention, s'il vous plaît ! C'est la chose la plus importante à comprendre sur le fonctionnement des références et des méthodes. Le fait est que lorsque nous appelons la méthode goToFuture(Cat cat) , c'est une copie de la référence à l'objet cat qui est transmise, pas la référence elle-même. Ainsi, lorsque nous passons un objet à une méthode, il y a deux références à l'objet. C'est très important pour comprendre ce qui se passe. C'est précisément pourquoi l'âge du chat n'a pas changé dans notre dernier exemple. Dans l'exemple précédent, lors du changement d'âge, on prenait simplement la référence passée au goToFuture()et l'a utilisé pour trouver l'objet en mémoire et changer son âge ( cat.age += 10 ). Mais maintenant, dans la méthode goToFuture() , nous créons un nouvel objet ( cat = new Cat(cat.age) ), et cet objet se voit attribuer la même copie de référence qui a été transmise à la méthode. Par conséquent:
  • La première référence ( Cat smudge = new Cat (5) ) pointe vers le chat d'origine (âgé de 5 ans)
  • Après cela, lorsque nous avons passé la variable cat à la méthode goToPast() et lui avons assigné un nouvel objet, la référence a été copiée.
Et cela nous a amené au résultat final : deux références pointant vers deux objets différents. Mais nous n'avons changé que l'âge de l'un d'entre eux (celui créé à l'intérieur de la méthode).
cat.age += 10;
Et bien sûr, dans la méthode main() on peut voir sur la console que l'âge du chat, smudge.age , n'a pas changé. Après tout, smudge est une variable de référence qui pointe toujours vers l'ancien objet d'origine avec l'âge de 5 ans, et nous n'avons rien fait avec cet objet. Tous nos changements d'âge ont été effectués sur le nouvel objet. Ainsi, il s'avère que les objets sont passés aux méthodes par référence. Les copies d'objets ne sont jamais créées automatiquement. Si vous passez un objet chat à une méthode et modifiez son âge, vous changerez son âge. Mais les variables de référence sont copiées lors de l'attribution de valeurs et/ou de l'appel de méthodes ! Répétons ici ce que nous avons dit à propos du passage des primitives : "Lorsque nous appelons la méthode changeInt() et passons l' intvariable x (=15) , la méthode n'obtient pas la variable x elle-même, mais plutôt une copie de celle-ci. Par conséquent, toute modification apportée à la copie n'affecte pas notre x d'origineNous finirons toujours par nous disputer plus d'une fois sur la façon dont les arguments sont passés en Java (même parmi les développeurs expérimentés). Mais, maintenant vous savez exactement comment cela fonctionne. Continue comme ça! :) Pour renforcer ce que vous avez appris, nous vous suggérons de regarder une leçon vidéo de notre cours Java
Commentaires
  • Populaires
  • Nouveau
  • Anciennes
Tu dois être connecté(e) pour laisser un commentaire
Cette page ne comporte pas encore de commentaires