Java dla Testerów 21. Przesłanianie metod

W tej lekcji pokażę Ci czym jest przesłanianie metod. Odpowiem tez na pytanie czym się różni przeciążanie metod od przesłaniania.

Sygnatura metody

Zanim przejdziemy do zagadnienia przesłaniania metod, przypomnę Ci czym jest sygnatura metody. Będzie nam to za chwilę potrzebne.

Sygnatura metody to nazwa metody wraz z typami jej parametrów. Popatrz na poniższy przykład (za dokumentacją):

public double calculateAnswer(double wingSpan, int numberOfEngines,
                              double length, double grossTons) {
    //do the calculation here
}

Sygnaturą takiej metody będzie: calculateAnswer(double, int, double, double). Jak widzisz nie ma tutaj typu zwracanego metody, jedynie typu parametrów i nazwa metody.

Przesłanianie metod

W poprzedniej lekcji omówiłam przeciążanie metod. Tam tworzyliśmy w jednej klasie kilka metod o tej samej nazwie, ale innej sygnaturze.

Z przesłanianiem metod mamy do czynienia, gdy mamy klasę bazową i klasę pochodną (dziedziczącą po klasie bazowej). Jeżeli w klasie pochodnej mamy metodę o takiej samej sygnaturze jak metoda w klasie bazowej, to przesłaniamy tę metodę. To znaczy przesłaniamy metodę w klasie nadrzędnej metodą w klasie bazowej.

Dodatkowo typ zwracany obu metod musi być taki sam. Metoda przesłaniająca (w klasie pochodnej) może zwracać inny typ niż metoda w klasie bazowej, ale musi to być podtyp typu zwracanego w metodzie klasy bazowej.

Adnotacja @Override

Gdy przesłaniamy metody warto użyć adnotacji @Override. Ta adnotacja mówi, że dana metoda w klasie pochodnej powinna przesłaniać metodę w klasie bazowej. Dzięki temu, jeżeli metoda oznaczona przez @Override nie będzie przesłaniała innej metody, kompilator nas o tym poinformuje.

Kod

PlanetTests.java

package Przeciążanie;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class PlanetTests {
    @Test
    public void info_NoParametersProvided_ReturnsFullInfo(){
        Planet mars = new Planet("Mars", 1.026, 6787, 2, false);
        Assertions.assertEquals("Name: Mars\n" +
                "Rotation period (days): 1.026\n" +
                "Diameter (km): 6787\n" +
                "Moons: 2\n" +
                "Has rings?: false",
                mars.info());
    }

    @Test
    public void info_MessageProvided_ReturnsFullInfo(){
        Planet mars = new Planet("Mars", 1.026, 6787, 2, false);
        String message = "This is the favourite one!";
        Assertions.assertEquals("Name: Mars\n" +
                        "Rotation period (days): 1.026\n" +
                        "Diameter (km): 6787\n" +
                        "Moons: 2\n" +
                        "Has rings?: false" +
                        "\n\n" + message,
                mars.info(message));
    }
}

Planet.java

package Przeciążanie;

public class Planet extends AstronomicalObject{
    private String name;
    private double rotationPeriodInDays;
    private int diameter;
    private int numberOfMoons;
    private boolean hasRings;

    public Planet(String name, double rotationPeriodInDays, int diameter, int numberOfMoons, boolean hasRings) {
        this.name = name;
        this.rotationPeriodInDays = rotationPeriodInDays;
        this.diameter = diameter;
        this.numberOfMoons = numberOfMoons;
        this.hasRings = hasRings;
    }
    public Planet(String name) {
        this.name = name;
    }

    public String info(){
        return ("Name: " + name +
                "\nRotation period (days): " + rotationPeriodInDays +
                "\nDiameter (km): " + diameter +
                "\nMoons: " + numberOfMoons +
                "\nHas rings?: " + hasRings);
    }
    @Override
    public String info(String message){
        return ("Name: " + name +
                "\nRotation period (days): " + rotationPeriodInDays +
                "\nDiameter (km): " + diameter +
                "\nMoons: " + numberOfMoons +
                "\nHas rings?: " + hasRings +
                "\n\n" + message);
    }
}

AstronomicalObject.java

package Przeciążanie;

public class AstronomicalObject {
    public String info(String message){
        return "Some generic message.";
    }
}