Wykład 7: Pakiety i Interfejsy
Transkrypt
Wykład 7: Pakiety i Interfejsy
Wykład 7: Pakiety i Interfejsy Plik Źródłowy w Javie Składa się z: instrukcji pakietu (pojedyncza, opcjonalna) ● instrukcji importujących (wielokrotne, opcjonalne) ● deklaracji klasy publicznej (pojedyncza, wymagana) ● deklaracji klas prywatnych (wielokrotne, opcjonalne) ● Wystarczy więc jedna deklaracja klasy publicznej. Pakiety w Javie Do tej pory, wszystkie klas pochodziły z tej samej przestrzeni nazw. Jak zapewnić by nazwy były unikalne? Pakiet - zbiornik na klasy: dzieli przestrzeń nazw na rozłączne zbiory ● kontroluje widoczność klas i składowych klas ● Definicja Pakietu Instrukcja pakietu umieszczona jako pierwsza komenda pliku źródłowego: package MojPakiet; Wszystkie klasy w pliku należą do pakietu MojPakiet. ● Inne pliki mogą posiadać tą samą instrukcję: pakiet rozkłada się na wiele plików. ● Wszystkie pliki .class w pakiecie MojPakiet są zapisywane w katalogu MojPakiet. ● Hierarchia Pakietów Pakiet wielo-poziomowy: package pakiet1.pakiet11.pakiet111; Pliki zachowane w katalogu: pakiet1/pakiet11/pakiet111 pakiet1\pakiet11\pakiet111 pakiet1:pakiet11:pakiet111 system Unix system Windows system Macintosh Zmienna CLASSPATH Zmienna środowiskowa która wskazuje na początek (korzeń) hierarchii pakietów w systemie. Np. katalog bieżący i katalog C:\mojaJava .;C:\mojaJava Java poszukuje pakietów przeszukując kolejne katalogi wymienione w ścieżce CLASSPATH. Pakiety: Przykład package MojPakiet; class Balans { String nazwa; double balans; Balans(String n, double b) { name = n; bal = b; } } void pokaz() { if (balans < 0) System.out.println(name + ": $" + bal); } Pakiety: Przykład class Pakiet { public static void main(String args[]) { Balans biezacy[] = new Balans[3]; biezacy[0] = new Balans("T.Bialy", 123.12); biezacy[1] = new Balans("J.Schmidt", 56.12); biezacy[2] = new Balans("A.Moraw", 34.75); for (int i = 0; i < 3; i++) biezacy[i].pokaz(); } } Pakiety: Przykład Należy umieścić pliki .class w katalogu pakietu: cd MojPakiet javac Pakiet.java Należy uruchomić klasę odwołując się do nazwy pakietu, z poziomu gdzie katalog MojPakiet jest widoczny: cd .. java MojPakiet.Pakiet Zakładamy że katalog bieżący jest w CLASSPATH. Ochrona Dostępu: Klasa Klasa dostępna w całym programie: public class MojaKlasa { ... } Klasa dostępna tylko w ramach tego samego pakietu: class MojaKlasa { ... } Ochrona Dostępu: Składowe Klasy Składowa dostępna w całym programie: public int pole; public int metoda(...){ ... } Składowa dostępna tylko w ramach danej klasy: private int pole; private int metoda(...){ ... } Ochrona Dostępu: Składowe Klasy Składowa dostępna w pod-klasach danej klasy i innych klasach w bieżącym pakiecie (dostęp domyślny!): int pole; int metoda(...){ ... } Składowa dostępna tylko w pod-klasach danej klasy (również poza bieżącym pakietem): protected int pole; protected int metoda(...){ ... } Ochrona Dostępu: Składowe Klasy private default protected public jedna klasa tak tak tak tak jeden pakiet pod-klasa nie tak tak tak jeden pakiet nie pod-klasa nie tak tak tak różne pakiety pod-klasa nie nie tak tak różne pakiety nie pod-klasa nie nie nie tak Ochrona Dostępu: Przykład Nad-klasa w pakiecie p1: package p1; public class NadKlasa { int n = 1; private int nPriv = 2; protected int nProt = 3; public int nPub = 4; public NadKlasa() { System.out.println("NadKlasa"); System.out.println("n = " + n); System.out.println("nPrivate = " + nPriv); System.out.println("nProtected = " + nProt); System.out.println("nPublic = " + nPub); } } Ochrona Dostępu: Przykład Pod-klasa w pakiecie p1: package p1; class PodKlasa extends NadKlasa { PodKlasa() { System.out.println("PodKlasa"); System.out.println("n = " + n); //System.out.println("nPrivate = " + nPriv); System.out.println("nProtected = " + nProt); System.out.println("nPublic = " + nPub); } } Ochrona Dostępu: Przykład Inna klasa w pakiecie p1: package p1; class JedenPakiet { JedenPakiet() { NadKlasa k = new NadKlasa(); System.out.println("JedenPakiet"); System.out.println("n = " + k.n); //System.out.println("nPrivate =" + k.nPriv); System.out.println("nProtected =" + k.nProt); System.out.println("nPublic =" + k.nPub); } } Ochrona Dostępu: Przykład Klasa wykonawcza w pakiecie p1: package p1; public class Pakiet1 { public static void main(String args[]) { NadKlasa k1 = new NadKlasa(); PodKlasa k2 = new PodKlasa(); JedenPakiet k3 = new JedenPakiet(); } } Ochrona Dostępu: Przykład Nad-klasa w pakiecie p2: package p2; class NadKlasa2 extends p1.NadKlasa { NadKlasa2() { System.out.println("NadKlasa2"); //System.out.println("n = " + n); //System.out.println("nPrivate = " + nPriv); System.out.println("nProtected = " + nProt); System.out.println("nPublic = " + nPub); } } Ochrona Dostępu: Przykład Inna klasa w pakiecie p2: package p2; class InnyPakiet { InnyPakiet() { p1.NadKlasa k = new p1.NadKlasa(); System.out.println("InnyPakiet"); //System.out.println("n = " + k.n); //System.out.println("nPrivate =" + k.nPriv); //System.out.println("nProtected ="+k.nProt); System.out.println("nPublic = " + k.nPub); } } Ochrona Dostępu: Przykład Klasa wykonawcza w pakiecie p2: package p2; public class Pakiet2 { public static void main(String args[]) { } } NadKlasa2 k1 = new NadKlasa2(); InnyPakiet k2 = new InnyPakiet(); Importowanie Pakietów Umożliwia bezpośrednie odwołanie do klasy przez jej nazwę, bez potrzeby wymieniania wszystkich pakietów. Importowanie konkretnej klasy: import pakiet1.pakiet2.klasa; Importowanie wszystkich klas danego pakietu: import pakiet1.pakiet2.*; Deklaracja Import Występuje zaraz po instrukcji pakietu, a przed deklaracją klasy: package pakiet; import pakiet1.pakiet2.klasa; class Klasa { ... } Kompilator domyślnie przyjmuje tą deklarację: import java.lang.*; Konflikty Nazw Jeśli klasa o tej samej nazwie występuje w dwóch różnych pakietach importowanych do programu: import pakiet1.*; import pakiet2.*; kompilator wyświetli komunikat błędu gdy spróbujemy użyć jednej z klas. Należy wówczas użyć pełnej nazwy: pakiet1.Klasa pakiet2.Klasa Odwołania Skrócone i Pełne Odwołanie skrócone: import java.util.*; class MojaKlasa extends Date { ... } Odwołanie pełne: class MojaKlasa extends java.util.Date { ... } Tylko składowe public w importowanym pakiecie, są dostępne dla nie-pod-klas w importującym kodzie. Importowanie Klas: Przykład package MojPakiet; public class Balans { String nazwa; double balans; public Balans(String n, double b) { nazwa = n; balans = b; } } public void pokaz() { if (balans < 0) System.out.println(nazwa + ":$" + balans); } Importowanie Klas: Przykład import MojPakiet.*; class Importowanie { public static void main(String args[]) { Balans test = new Balans("T.Bialy",-12.57); test.pokaz(); } } Interfejs Interfejs jest podobny do klasy która posiada tylko metody pozbawione implementacji. wiele klas może implementować jeden interfejs ● jedna klasa może implementować wiele interfejsów ● Klasa implementuje dany interfejs jeśli dostarcza definicji dla wszystkich jego metod. Definicja Interfejsu dostęp typ ... typ typ ... typ } interface nazwa { metoda1(lista-parametrów); metodaN(lista-parametrów); zmienna1 = wartość; zmiennaM = wartość; Dwa rodzaje dostępu: ● public – może być użyty gdziekolwiek w programie ● domyślny – dostępny tylko w bieżącym pakiecie Zmiennie są static, final, inicjowane stałą. Implementacja Interfejsu Ogólna postać definicji klasy: dostęp class nazwa extends nad-klasa implements interfejs1, ..., interfejsN { ... } Dostęp public lub domyślny. Metody implementujące interfejs muszą być public, oraz posiadać dokładnie ten sam typ jak w interfejsie. Interfejs: Przykład Deklaracja interfejsu: interface MojInterfejs { void metoda(int par); } Klasa implementująca interfejs: class Klasa implements MojInterfejs { public void metoda(int p) { System.out.println("parametr: " + p); } } Interfejs: Przykład Klasa implementująca może deklarować własne metody: class Klasa implements MojInterfejs { public void metoda(int p) { System.out.println("parametr: " + p); } } void innaMetoda() { System.out.println("Inna metoda"); } Interfejs i Zmienne Obiektowe Deklaracja zmiennej której typem jest interfejs. MojInterfejs mi; Wartością zmiennej może być odwołanie do obiektu dowolnej klasy która implementuje ten interfejs. MojInterfejs mi = new Klasa(); class Klasa implements MojInterfejs { ... } Wywołanie Metody przez Zmienną Przez zmienną której typem jest interfejs można wywołać dowolną metodę w tym interfejsie: mi.metoda(42); Nie można wywołać metody która nie jest w interfejsie: mi.innaMetoda(); Wywoła się poprawna wersja metody, odpowiednio dla faktycznego obiektu wskazywanego przez zmienną. Polimorfizm przez Interfejs interface MojInterfejs { void metoda(int par); } class Klasa1 implements MojInterfejs { public void metoda(int p) { System.out.println("parametr: " + p); } } class Klasa2 implements MojInterfejs { public void metoda(int p) { System.out.println("kwadrat: " + (p*p)); } } Polimorfizm przez Interfejs class PolimorfizmInterfejs { public static void main(String args[]) { MojInterfejs mi; Klasa1 k1 = new Klasa1(); Klasa2 k2 = new Klasa2(); mi = k1; mi.metoda(42); mi = k2; mi.metoda(6); } } Interfejs i Klasa Abstrakcyjna Klasa która zawiera interfejs, ale nie implementuje wszystkich jego metod, musi być abstrakcyjna. abstract class KlasaCzesciowa implements MojInterfejs { int a,b; void pokaz() { System.out.println(a + " " + b); } } Zmienne w Interfejsie Importowanie stałych do wielu klas przez interfejs który posiada tylko zmienne. import java.util.Random; interface Stale { int NIE = 0; int TAK = 1; int MOZE = 2; } Zmienne w Interfejsie: Przykład class Pytanie implements Stale { Random rand = new Random(); int pytanie() { int test = (int)(100* rand.nextDouble()); if (test < 30) return NIE; else if (test < 75) return MOZE; else return TAK; } } Zmienne w Interfejsie: Przykład class ZapytajMnie implements Stale { static void odpowiedz(int wynik) { switch(wynik) { case NIE:System.out.print("Nie");break; case TAK:System.out.print("Tak");break; case MOZE:System.out.print("Moze");break; } } } public static void main(String args[]) { Pytanie p = new Pytanie(); odpowiedz(p.pytanie()); odpowiedz(p.pytanie()); odpowiedz(p.pytanie()); } Dziedziczenie Interfejsów Jeden interfejs może dziedziczyć po innym: interface A { void metoda1(); void metoda2(); } interface B extends A { void metoda3(); } Klasa implementująca musi dostarczyć definicji dla wszystkich metod w kolejnych interfejsach. Dziedziczenie: Przykład class MojaKlasa implements B { public void metoda1() { System.out.println("metoda1"); } public void metoda2() { System.out.println("metoda2"); } public void metoda3() { System.out.println("metoda3"); } } Dziedziczenie: Przykład class InterfejsDziedziczenie { public static void main(String args[]) { MojaKlasa k = new MojaKlasa(); } } k.metoda1(); k.metoda2(); k.metoda3();