package gotowe.p12_dziedziczenie.a_podstawy;

public class Polimorfizm1 {

    public static void main(String[] args) {
        Osoba osoba = new Osoba("Ala", "Kowalska", 30);
        System.out.println(osoba);
        // Poprzez zmienną typu Osoba można korzystać tylko ze zmiennych (pól) i metod zdefiniowanych w klasie Osoba.
        System.out.println(osoba.imie + " " + osoba.nazwisko);
        osoba.przedstawSie();
        // Nie działają:
        // System.out.println(osoba.kierunek);
        // System.out.println(osoba.sredniaOcen());
        System.out.println();

        Student student = new Student("Adam", "Abacki", 22, "geologia", 4);
        System.out.println(student);

        // Jeśli klasa Student jest rozszerzeniem klasy Osoba,
        // to na zmiennej typu Student można wykonać te operacje (i dostać się do tych zmiennych),
        // które byłyby dostępne zmiennej typu Osoba...
        if(student.pelnoletnia()) {
            System.out.println("Student " + student.imie + " jest pełnoletni");
        }
        // ... a dodatkowo dostępne są zmienne i metody dodane w klasie Student.
        student.dodajOcene(5);
        student.dodajOcene(4);
        System.out.println("Średnia ocen: " + student.sredniaOcen());
        System.out.println();

        // Dziedziczenie to nie tylko "skopiowanie definicji z istniejącej klasy i dopisanie czegoś jeszcze".
        // W dziedziczeniu chodzi też o to, że w każdej sytuacji obiekt podklasy może być użyty zamiast obiektu nadklasy.
        // "zasada podstawiania"
        // Skoro student posiada wszystkie te cechy, co inne osoby, to obiektu student można użyć w k ązdym miejscu, gdzie możnaby uzyć osoby.

        // Przykłady:
        // Student może być wpisany do zmiennej typu Osoba.
        Osoba ktos = student;
        // Osoba ktos = osoba;
        ktos.przedstawSie();

        // Student może być właścicielem konta:
        Konto kontoStudenckie = new Konto(1313, 123, student);
        kontoStudenckie.wplata(500);
        System.out.println(kontoStudenckie);
        System.out.println();
        
        // Student może pójść do urzędu
        Urzad urzadMiasta = new Urzad();
        urzadMiasta.zalatwSprawe(student);
        // itp....

        // Czy w zmienne ktos mamy teraz Osobę czy Studenta?
        System.out.println(ktos.getClass()); // Student
        // Jednak do pól tego obiektu nie można dostać się "oficjalnie":
        // System.out.println(ktos.kierunek + " , średnia " + ktos.sredniaOcen());

        // Obiekt ze zmiennej typu "nadklasa" można zrzutować na typ "podklasa", jeśli widzimy, że w danym momencie jest to możliwe:
        if(ktos instanceof Student) {
            System.out.println("To jest Student");
            Student zrzutowany = (Student)ktos;
            System.out.println(zrzutowany.kierunek + " , średnia " + zrzutowany.sredniaOcen());
            // albo tak jeśli czytamy tylko jedną rzecz:
            System.out.println(((Student)ktos).rok);
        } else {
            System.out.println("To nie jest Student");
        }
    }

}
