package p11_klasy.podstawy_v6;

public class Polimorfizm1 {

	public static void main(String[] args) {
		Osoba osoba = new Osoba("Ala", "Kowalska", 30);
		Student student = new Student("Adam", "Abacki", 22, "geologia", 2);
		System.out.println(osoba);
		osoba.przedstawSie();
		System.out.println();
		
		System.out.println(student);
		student.przedstawSie();
		System.out.println();
		
		// Nawet, gdy zmienna jest typu Osoba, ale w tej zmiennej jest referencja do obiektu klasy Student,
		// to przy wywołaniu metody wykona się wersja z klasy Student.
		// W mechanizmie override decydujące znaczenie ma typ obiektu w czasie wykonania.
		
		Osoba ktos;
		ktos = osoba;
		ktos.przedstawSie();
		
		ktos = student;
		ktos.przedstawSie();
		System.out.println();
		
		Sklep sklep = new Sklep("Lidl", 6);
		sklep.sprzedajPiwo(osoba);
		sklep.sprzedajPiwo(student);
		
		// 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);
		
		// 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:
		// Gdyby w zmiennej ktos był obiekt klasy StudentInformatyki, to też wyszłoby true
		if(ktos instanceof Student) {
			// rzutowanie jest bezpieczne
			System.out.println( ((Student)ktos).rok );
		}
		
		// Od Javy 17 (?) jest dostępne instanceof, 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());
	}

}
