Wykład 5: Więcej o Klasach i Metodach
Przeciążanie Metod Klasa posiada dwie lub więcej metod o tej samej nazwie ale różnych deklaracjach parametrów. Java używa liczby i typów argumentów by ustalić którą wersję metody należy wywołać. Przeciążanie metod plus dziedziczenie to sposób na implementację polimorfizmu.
Demo: Przeciążanie Metod class Metody { void test() { System.out.println("Brak parametrow"); void test(int a) { System.out.println("a: " + a); void test(int a, int b) { System.out.println("a i b: " + a + " " + b); double test(double a) { System.out.println("double a: " + a); return a*a;
Demo: Przeciążanie Metod class PrzeciazanieMetod { public static void main(string args[]) { Metody m = new Metody(); double wynik; m.test(); m.test(10); m.test(10, 20); wynik = m.test(12.5); System.out.println("test(12.5): " + wynik);
Różne Typy Wyników Różne typy wynikowe nie wystarczają: double test(double a) { System.out.println("double a: " + a); return a*a; int test(double a) { System.out.println("double a: " + a); return (int)(a*a);
Przeciążanie i Konwersja Typów Automatyczna kowersja typów gdy nie istnieje metoda o dokładnym typie wywołania: void test() { System.out.println("Brak parametrow ); void test(double a) { System.out.println("double a: " + a); int i = 88; test(); test(i);
Przeciążanie i Polimorfizm W językach bez przeciążania, każda metoda musi posiadać unikalna nazwę: int abs(int i) long labs(long i) float fabs(float i) Java umożliwia wystąpienie powiązanych metod pod jedną nazwą: jeden interfejs, wiele metod. static int abs(int i) static long abs(long i) static float abs(float i)
Przeciążanie Konstruktorów Różne metody tworzena obiektów klasy przez przeciążanie konstruktorów. class Pudelko { double szerokosc; double wysokosc; double glebokosc; Obliczanie i wyświetlanie objętości: void objetosc() { System.out.println( szerokosc * wysokosc * glebokosc);
Przeciążanie Konstruktorów Konstruktory z trzema parametrami, z jednym parametrem, i bez parametrów. Pudelko(double s, double w, double g) { szerokosc = s; wysokosc = w; glebokosc = g Pudelko(double b) { szerokosc = wysokosc = glebokosc = b; Pudelko() { szerokosc = wysokosc = glebokosc = -1;
Demo: Przeciążanie Konstruktorów class PrzeciazanieKonstruktorow { public static void main(string args[]) { Pudelko p1 = new Pudelko(10,20,15); Pudelko p2 = new Pudelko(10); Pudelko p3 = new Pudelko(); p1.objetosc(); p2.objetosc(); p3.objetosc();
Obiekty jako Parametry Metoda może posiadać parametry typów prostych. Można też przekazywać do metody obiekty. class Test { int a, b; Test(int i, int j) { a = i; b = j; Czy obiekt bieżący jest równy parametrowi metody? boolean equals(test o) { if (o.a == a && o.b == b) return true; else return false;
Demo: Przekazywanie Obiektów class PrzekazywanieObiektowMetodom { public static void main(string args[]) { Test o1 = new Test(10,20); Test o2 = new Test(10,20); Test o3 = new Test(1,1); System.out.println( o1==o2: +o1.equals(o2)); System.out.println( o1==o3: +o1.equals(o3));
Inicjacja Obiektu Obiektem Często przekazujemy obiekty konstruktorom: jeden obiekt inicjalizuje drugi. class Pudelko { double szerokosc; double wysokosc; double glebokosc; Pudelko(Pudelko p) { szerokosc = p.szerokosc; wysokosc = p.wysokosc; glebokosc = p.glebokosc;...
Demo: Inicjacja Obiektu Obiektem class PrzekazywanieObiektowKonstruktorom { public static void main(string args[]) { Pudelko p1 = new Pudelko(10,20,30); Pudelko p2 = new Pudelko(p1); p1.objetosc(); p2.objetosc();
Przekazywanie Argumentów Dwie metody przekazywania argumentów metodom: przez wartość: przekazanie kopii wartości argumentu - zmiany parametru formalnego nie mają wpływu na wartość argumentu wywołania przez nazwę: przekazanie odwołania do argumentu zmiana parametru formalnego powoduje zmianę wartości argumentu wywołania Java używa obu metod.
Przekazywanie Typów Prostych Przekazywanie argumentów typów prostych odbywa się przez wartość. class Test { void metoda(int i, int j) { i *= 2; j /= 2;
Demo: Przekazywanie Typów Prostych class WywolaniePrzezWartosc { public static void main(string args[]) { Test o = new Test(); int a = 10; int b = 20; System.out.println( przed wywolaniem: + a + + b); o.metoda(a, b); System.out.println( po wywolaniu: + a + + b);
Przekazywanie Obiektów Obiekty przekazywane są przez nazwę: parametr uzyskuje ten sam adres obiektu jak argument. class Test { int a, b; Test(int i, int j) { a = i; b = j; void metoda(test o) { o.a *= 2; o.b /= 2;
Demo: Przekazywanie Obiektów class WywolaniePrzezNazwe { public static void main(string args[]) { Test o = new Test(10, 20); System.out.println( przed wywolaniem: + o.a + + o.b); o.metoda(o); System.out.println( po wywolaniu: + o.a + + o.b);
Zwracanie Obiektów Metody mogą zwracać wartości typów prostych, jak też obiekty dowolnych klas. class Test { int a; Test(int i) { a = i; Test dokwadratu() { Test temp = new Test(a * a); return temp;
Demo: Zwracanie Obiektów class ZwracanieObiektow { public static void main(string args[]) { Test o1 = new Test(2); Test o2; o2 = o1.dokwadratu(); System.out.println( o1.a: + o1.a); System.out.println( o2.a: + o2.a); o2 = o2.dokwadratu(); System.out.println( drugie wywolanie ); System.out.println( o2.a: + o2.a);
Rekursja Metoda rekurencyjna to metoda która wywołuje samą siebie (dla innych wartości argumentów): następuje alokacja pamięci na stosie dla zmiennych lokalnych i parametrów kod metody jest wywołany ponownie dla nowych wartości argumentów powrót powoduje usunięcie ze stosu parametrów i zmiennych, i kontynuację za punktem wywołania
Demo: Rekursja class Silnia { int silnia(int n) { if (n == 1) return 1; return n * silnia(n-1); class Rekursja { public static void main(string args[]) { Silnia s = new Silnia(); System.out.println( dla 3: + s.silnia(3)); System.out.println( dla 5: + s.silnia(5)); System.out.println( dla 8: + s.silnia(8));
Demo: Rekursja i Tablice class Tablica { int wartosci[]; Tablica(int i) { wartosci = new int[i]; void wyswietltablice(int i) { if (i == 0) return; else wyswietltablice(i-1); System.out.print( [ + (i-1) + ] ); System.out.println(wartosci[i-1]);
Demo: Rekursja i Tablice class RekursjaDlaTablic { public static void main(string args[]) { Tablica t = new Tablica(10); int i; for (i=0; i<10; i++) t.wartosci[i] = i; t.wyswietltablice(10);
Kontrola Dostępu Enkapsulacja umożliwia: połączenie danych i kodu, oraz kontrolę dostępu do wnętrza klasy. Zapobiega użyciu klasy w sposób niepożądany, np. aby dane były dostępne przez dostarczone metody. Umożliwia wymianę implementacji przy zachowaniu interfejsu klasy.
Kontrola Dostępu Cztery specyfikatory dostępu do elementów klasy: public dostępny dla każdej części programu private tylko dla składowych danej klasy default public dla składowych pakietu gdzie znajduje się element, private dla reszty protected opisany później Specyfikator poprzedza resztę definicji elementu: private int i; public static void main(...)
Demo: Kontrola Dostępu class Test { int a; public int b; private int c; void zmienc(int i) { c = i; int zwrocc() { return c;
Demo: Kontrola Dostępu class KontrolaDostepu { public static void main(string args[]) { Test t = new Test(); t.a = 10; t.b = 20; // t.c = 30!BLAD! t.zmienc(30); System.out.print( a, b i c: + t.a + ); System.out.println(t.b + + t.zwrocc());
Demo: Stos i Kontrola Dostępu class Stos { private int stos[] = new int[10]; private int wskaznik; Stos() {... void push(int element) {... int pop() {...
Statyczne Składowe Klasy Normalnie, elementy klasy (pola i metody) mogą być tylko użyte poprzez obiekty tej klasy. Elementy statyczne są niezależne od obiektów klasy: statyczne dane static int dane; statyczna metoda static void metoda(); statyczny blok inicjacja elementów statycznych static {...
Statyczne Składowe Klasy Sposób wywołania: nazwaklasy.metoda() nazwaklasy.zmienna Ograniczenia: tylko odwołania do metod i danych statycznych nie mogą zawierać odwołań do this czy super
Demo: Statyczne Składowe Klasy class SkladoweStatyczne { static int a = 3; static int b; static void metoda(int x) { System.out.println( x = + x); System.out.println( a = + a); System.out.println( b = + b); //wykonywany raz gdy klasa jest ladowana static { System.out.println( Inicjalizacja ); b = a * 4 public static void main(string args[]) { metoda(42);
Demo: Wywołanie Statyczne class Statyczne { static int a = 3; static int b = 99; static void wywolajmnie() { System.out.println( a = + a); class WywolanieStatyczne { public static void main(string args[]) { Statyczne.wywolajMnie(); System.out.print( b = ); System.out.println(Statyczne.b);
Zmienne Final Deklaracja zmiennej jako final zapobiega zmianie jej wartości po zainicjowaniu. final int FILE_NEW = 1; final int FILE_OPEN = 2; final int FILE_CLOSE = 3; Zmienna jest faktycznie stałą. Metody są też deklarowane jako final ale znaczenie tego jest zupełnie odmienne.
Tablice jako Obiekty Tablica jest zaimplementowana jako obiekt. Jednym z atrybutów tego obiektu jest length: ilość elementów które tablica może zawierać. class DlugoscTablicy { public static void main(string args[]) { int a1[] = new int[10]; int a2[] = {3, 5, 7, 9, 11, 13, 15, 17; System.out.println( a1: + a1.length); System.out.println( a2: + a2.length);
Demo: Stos Dowolnej Długości class Stos { private int stos[]; private int wskaznik; Stos(int rozmiar) { stos = new int[rozmiar]; wskaznik = -1; void push(int element) { if (wskaznik == stos.length-1) System.out.println("Stos jest pelny."); else stos[++wskaznik] = element; int pop() {...
Klasa Zagnieżdżona Klasa zagnieżdżona: definiowana wewnątrz innej klasy. Ma dostęp do wszystkich elementów, również prywatnych, klasy zewnętrznej. Nie jest widoczna na zewnątrz klasy zewnętrznej. Klasa zewnętrzna ma dostęp do klasy zagnieżdżonej, ale nie jej elementów. Statyczna klasa zagnieżdżona: musi odwoływać się do elementów klasy zewnętrznej przez obiekty tej klasy.
Klasa Wewnętrzna Nie-statyczna klasa zagnieżdżona: ma bezpośredni dostęp do zmiennych i metod klasy zewnętrznej. class Zewnetrzna { int x = 100; class Wewnetrzna { int y = 200; void wyswietl() { System.out.println( x = + x);
Klasa Wewnętrzna void test() { Wewnetrzna w = new Wewnetrzna(); w.wyswietl(); //System.out.println(y); //!BLAD! class KlasaWewnetrzna { public static void main(string args[]) { //Wewnetrzna w = new Wewnetrzna(); //!BLAD! Zewnetrzna z = new Zewnetrzna(); z.test();