Commit f470f6d4 by Patryk Czarnik

Polimorfizm i nadpisywanie metod

parent d3cc72e6
package p10_klasy.v4;
public class Dziedziczenie2 {
public static void main(String[] args) {
Osoba osoba = new Osoba("Ala", "Kowalska", 30);
System.out.println(osoba);
Student student = new Student("Adam", "Abacki", 21, "geologia", 1);
System.out.println(student);
// Metoda przedstaw się działa w inny sposób dla osoby, w inny dla studenta
osoba.przedstawSie();
student.przedstawSie();
System.out.println();
Osoba ktos;
// Do zmiennej typu Osoba można wpisać obiekt klasy Osoba:
ktos = osoba;
// Teraz metoda przedstawSie działa w wersji podstawowej:
ktos.przedstawSie();
// Do zmiennej typu Osoba można jednak wpisać także obiekt klasy Student
ktos = student;
// Teraz metoda przedstawSie zadziała w wersji z klasy Student
ktos.przedstawSie();
// ! To faktyczna klasa obiektu decyduje o tym, czy wykona się metoda z nadklasy, czy z podklasy ! //
// Zauważmy, że ze zmiennej ktos nie da się odczytać pól kierunek i rok, czy ocen
// System.out.println(ktos.kierunek);
// Bo "nie każda Osoba ma te dane"
// Ale obiekt można zrzutować do zmiennej typu Student.
// Jeśli wiemy, że w zmiennej ktos na pewno jest Student, to można tak:
Student s1 = (Student)ktos;
System.out.println(s1.kierunek);
System.out.println( ((Student)ktos).rok );
// Ale jeśli w zmiennej nie studenta, tylko zwykła osoba, to będzie wyjątek ClassCastException
// Student s2 = (Student)osoba;
// System.out.println(s2.kierunek);
String napis = "Jestę studentę";
// To się w ogóle nie skompiluje:
// Student s3 = (Student)napis;
// Jest sposób, aby to obejsc. Poniższe się kompiluje, ale powoduje wyjątek:
// Student s4 = (Student)(Object)napis;
// Metoda getClass zwraca aktualną informację o tym, jakiej kalsy jest obiekt.
System.out.println(ktos.getClass());
// Aby sprawdzić, czy rzutowanie będzie możliwe, używamy instanceof:
if(ktos instanceof Student) {
// rzutowanie jest bezpieczne
System.out.println( ((Student)ktos).rok );
}
// Od Javy 17 (?) jest dostępne instancof, które od razu wpisuje wynik do zmiennej:
if(ktos instanceof Student s5) {
s5.dodajOcene(4);
s5.dodajOcene(5);
System.out.println(s5.sredniaOcen());
}
// Przypisanie do zmiennej i rzutowanie nie tworzą nowych obiektów, tylko cały czas odnosimy się do tego samego obiektu.
student.kierunek = "zoologia";
student.dodajOcene(5);
System.out.println();
ktos.przedstawSie();
System.out.println(student.oceny);
System.out.println(student.sredniaOcen());
System.out.println(((Student)ktos).sredniaOcen());
}
}
package p10_klasy.v4;
public class Dziedziczenie3 {
public static void main(String[] args) {
// Dzięki temu, że "Student jest Osobą" i "Pracownik jest Osobą",
// można obiekty tych klas umieści w tablicy (kolekcji itp.) osób.
Osoba[] osoby = {
new Osoba("Ala", "Kowalska", 44),
new Osoba("Ola", "Malinowska", 13),
new Student("Adam", "Abacki", 20, "medycyna", 1),
new StudentInformatyki("Karol", "Infobacki", 23, 3),
new Pracownik("Jan", "Kowalski", 40, "kierowca", 3300),
};
// Wtedy gdy przeglądamy zawartość w pętli element kolekcji widzimy jako obiekt nadklasy (Osoba)
System.out.println("przedstawSie w pętli for:");
for(Osoba o : osoby) {
o.przedstawSie();
System.out.println(" to jest obiekt klasy: " + o.getClass().getSimpleName());
// Można jawnie sprawdzić czy zmienna wskazuje na obiekt określonej klasy
// (lub dalszej podklasy - np. StudentInformatyki byłby w tym sensie Studentem)
if(o instanceof Student) {
// Jeśli tak jest, to możemy bezpiecznie zrzutować (cast) zmienną na typ Student
Student student = (Student) o;
System.out.println(" To jest student kierunku " + student.kierunek
+ ", który ma średnią ocen " + student.sredniaOcen());
}
// natomiast taki if nie byłby prawdziwy dla obiektu klasy StudentInformatyki
if(o.getClass() == Student.class) {
System.out.println(" to jest konkretnie klasy Student");
}
}
}
}
package p10_klasy.v4;
public class Dziedziczenie4_Zakupy {
public static void main(String[] args) {
Osoba[] osoby = {
new Osoba("Ala", "Kowalska", 44),
new Osoba("Ola", "Malinowska", 13),
new Student("Adam", "Abacki", 20, "medycyna", 1),
new StudentInformatyki("Karol", "Infobacki", 23, 3),
new Pracownik("Jan", "Kowalski", 40, "kierowca", 3300),
};
System.out.println("Idziemy do sklepu...");
Sklep sklep = new Sklep("Biedronka", 5);
for(Osoba o : osoby) {
sklep.sprzedajPiwo(o, 1);
}
}
}
package p10_klasy.v4;
import java.math.BigDecimal;
// W Javie nie ma "wielodziedziczenia", klasa ma dokładnie jedną nadklasę.
class Pracownik extends Osoba {
private final static int PENSJA_MINIMALNA = 4000;
String zawod;
BigDecimal pensja;
Pracownik() {
}
Pracownik(String imie, String nazwisko, int wiek, String zawod, BigDecimal pensja) {
// wywołanie konstruktora z nadklasy
super(imie, nazwisko, wiek);
this.zawod = zawod;
this.pensja = pensja;
}
Pracownik(String imie, String nazwisko, int wiek, String zawod, double pensja) {
// wywołanie innego konstruktora z tej samej klasy
this(imie, nazwisko, wiek, zawod, BigDecimal.valueOf(pensja).setScale(2));
}
Pracownik(String imie, String nazwisko, int wiek, String zawod, int pensja) {
this(imie, nazwisko, wiek, zawod, BigDecimal.valueOf(pensja).setScale(2));
}
Pracownik(String imie, String nazwisko, int wiek, String zawod, String pensja) {
this(imie, nazwisko, wiek, zawod, new BigDecimal(pensja));
}
Pracownik(String imie, String nazwisko, int wiek, String zawod) {
this(imie, nazwisko, wiek, zawod, PENSJA_MINIMALNA);
}
// tworzenie wielu konstruktorów w tej samej klasie to jest "przeciążanie konstruktorów" / "overloading"
@Override
public void przedstawSie() {
System.out.println("Dzień dobry, tu "+ imie + ", pracuję jako " + zawod + " i zarabiam " + pensja +" zł.");
}
@Override
public String toString() {
return "Pracownik [zawod=" + zawod + ", pensja=" + pensja + ", imie=" + imie + ", nazwisko=" + nazwisko
+ ", wiek=" + wiek + "]";
}
}
...@@ -17,6 +17,13 @@ class Student extends Osoba { ...@@ -17,6 +17,13 @@ class Student extends Osoba {
this.rok = rok; this.rok = rok;
} }
// Jeśli chodzi o metody, podklasa może
// 1) Nie zmieniać metod odziedziczonych z nadklasy
// przykłady: jestPelnoletnia()
// Taka metoda w nadklasie może być zadeklarowana jako "final" - to znaczy,
// że jest to ostateczna definicja i podklasa nie może jeje zmienić
// 2) Dodać nowe metody, których nie było w nadklasie
void dodajOcene(int ocena) { void dodajOcene(int ocena) {
oceny.add(ocena); oceny.add(ocena);
} }
...@@ -24,4 +31,23 @@ class Student extends Osoba { ...@@ -24,4 +31,23 @@ class Student extends Osoba {
double sredniaOcen() { double sredniaOcen() {
return oceny.stream().mapToInt(Integer::intValue).average().orElse(0.0); return oceny.stream().mapToInt(Integer::intValue).average().orElse(0.0);
} }
// 3) Nadpisać (override) metody, które były zdefiniowane w nadklasie
// czyli dla istniejących metoda podać inną treść.
@Override
void przedstawSie() {
System.out.println("Hej tu "+ imie + " " + nazwisko
+ ", studiuję kierunek " + kierunek + ", jestem na " + rok + " roku.");
}
// Od Javy 5 przed definicją metody, która nadpisuje definicję z nadklasy, można umieścić adnotację @Override
// Ważne: nawet bez tej adnotacji nadpisanie jest skuteczne. Adnotacja tylko:
// - zwiększa czytelność kodu ("rzuca się w oczy")
// - powoduje błąd kompilacji, gdyby okazało się, że jednak tutaj nie nadpisujemy metody, tylko definiujemy nową (np. literówka w nazwie, parametry innego typu)
@Override
public String toString() {
// do tego, co zwraca toString zdefiniowany w klasie Osoba, dodaję info o roku i kierunku studiów:
return super.toString() + ", studiuje na " + rok + " roku kierunku " + kierunek;
}
} }
package p10_klasy.v4;
class StudentInformatyki extends Student {
// Czasami podklasa nie ma nowych pól ani metod,
// a jest wprowadzana po to, aby ustalić pewne szczegóły
// Jest to podklasa / podzbiór w sensie matematycznym (logicznym).
public StudentInformatyki(String imie, String nazwisko, int wiek, int rok) {
// ustalamy, że kierunkiem studiów jest "informatyka" i nie może być inaczej
super(imie, nazwisko, wiek, "informatyka", rok);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment