Przesłanianie metod w Java podstawy

0

Siemka, dlaczego mój kompilator nie pozwala mi skompilować takiego kodu

public class Main {
	public static void main(String[] args) {
		
//1 sposób
		Pochodna i1 = new Pochodna();
        long j1 = i1.sum();
        System.out.println(j1);
        
//2 sposób
        Bazowa i2 = new Pochodna();
        long j2 = i2.sum(); //tu błąd
        System.out.println(j2);
	}
}

class Bazowa {
	public Number sum() {
    	return 31;
    }
}

class Pochodna extends Bazowa{
	@Override
	public Long sum() {
		System.out.println("Metoda z klasy podrzednej.");
		return super.sum().longValue() + 500L;
	}
}

Pierwsze 3 instrukcje w metodzie main wykonują się prawidłowo, natomiast w kolejnych 3 kompilator nie pozwala mi przypisać wartości z metody sum() do zmiennej j2 bo twierdzi że
"Type mismatch: cannot convert from Number to long" a moja przesłonięta metoda zwraca przecież Long a nie Number.
Jestem pewny że metoda prawidłowo została przesłonięta ponieważ dodatkowo drukuje napis w konsoli przy wykonaniu.
Pierwszy sposób działa bez zarzutu, a drugi się nie kompiluje czy mógłby mi ktoś wyjaśnić czym one się różnią i dlaczego wychodzi ten błąd, z góry dzięki ;)

4

Ponieważ referencja i2 jest typu Bazowa.
Kompilator w następnej lini nie zakłada że masz typ Pochodna, tylko że Bazowa.

4

"Type mismatch: cannot convert from Number to long" a moja przesłonięta metoda zwraca przecież Long a nie Number.

Ale skąd niby kompilator ma wiedzieć jaki typ tam masz? Kompilator widzi tam tylko sygnatury z metod klasy bazowej. Żeby wyjaśnic ci problem zmodyfikujmy lekko ten program:

class Bazowa {
    public Object sum() {
        return 31;
    }
}

class Pochodna extends Bazowa{
    @Override
    public Long sum() {
        return super.sum().longValue() + 500L;
    }

class PochodnaDruga extends Bazowa{
    @Override
    public String sum() {
        return "xakep";
    }
}

I teraz napiszmy taki kod:

Bazowa x = null;
if(new Random().nextBoolean()){
    x = new Pochodna();
} else {
    x = new PochodnaDruga();
}

? zmienna = x.sum();

I co teraz? Jakiego typu ma być zmienna? Losowo przy każdym uruchomieniu programu xmoże być jednego albo drugiego typu, czyli zwracać longa albo stringa. Na etapie kompilacji nie dałoby się tego stwierdzić. Dlatego kompilator patrzy tylko i wyłącznie na sygnaturę z klasy bazowej i pozwoli ci tam użyć tylko Object.

1 użytkowników online, w tym zalogowanych: 0, gości: 1