Programowanie obiektowe - Wyklad 01
Transkrypt
Programowanie obiektowe - Wyklad 01
Programowanie obiektowe Wykład 01 Maciej Wołoszyn mailto:[email protected]∗ 27 lutego 2008 Spis treści 1 Java 1.1 1.2 1.3 2 Najważniejsze cechy j˛ezyka . . . . . . . . . . . . . . . . . . . . . . . . . . Składnia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Przykładowy program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 3 2 Typy danych 3 3 Operatory 5 4 Klasy 8 4.1 4.2 4.3 Składowe static . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dost˛ep do składników . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dost˛ep do klas i nazwy plików źródłowych . . . . . . . . . . . . . . . . . . 11 12 12 5 Klasy biblioteczne 12 6 Tablice 14 6.1 6.2 15 16 7 Tablice wielowymiarowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . Klasa Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Styl – konwencje, nazewnictwo itp. 16 ∗ Prosz˛ e o przesyłanie na ten adres informacji o znalezionych bł˛edach, literówkach oraz propozycji zmian i uzupełnień. Dokument przygotowano za pomoca˛ systemu LATEX. Wszelkie prawa zastrzeżone. 1 Programowanie obiektowe. Wykład 01 2 1 Java • j˛ezyk programowania zaprojektowany przez firm˛e Sun ( → http://java.sun.com ) 1.1 Najważniejsze cechy jezyka ˛ • niezależny od architektury – programy napisane w j˛ezyku Java można uruchamiać w wielu systemach operacyjnych komputerów, a także na różnych innych urzadzeniach ˛ (np. telefony) – kod źródłowy kompiluje si˛e do postaci pośredniej (tzw. bytecode, uniwersalny dla wszystkich obsługiwanych systemów operacyjnych) – do uruchomienia potrzebna jest wirtualna maszyna Javy (JVM, zależne od systemu operacyjnego środowisko uruchomieniowe; np. zawarte w pakiecie JSE firmy Sun) – w efekcie także: ∗ mniejsza wydajność w porównaniu do j˛ezyków typu C czy C++ – ale stale poprawiana za pomoca˛ mechanizmów takich jak just-in-time compilation (JIT) ∗ wi˛eksze zużycie zasobów komputera • zastosowanie metodologii obiektowej – zaimplementowana od podstaw; pierwotnym zamiarem twórców Javy było zastapienie ˛ C++ • wbudowana obsługa m.in. sieci komputerowych, graficznego interfejsu użytkownika, wielowatkowości ˛ ⇒ wraz z Java˛ dostarczana jest bardzo obszerna biblioteka klas 1.2 Składnia • oparta na C i C++ : podobny sposób zapisu programu, definiowana zmiennych, funkcji, bloków instrukcji; identyczne instrukcje sterujace ˛ takie jak np.: – – – – if for while switch Programowanie obiektowe. Wykład 01 3 1.3 Przykładowy program Plik MojProgram.java: // plik MUSI sie nazywac MojProgram.java ! public class MojProgram { public static void main(String[] args) { System.out.println("[MojProgram!]"); } } • odpowiednikiem wyst˛epujacej ˛ w C i C++ funkcji main(int argc, char* argv[]) jest zawarta w publicznie dost˛epnej klasie metoda public static void main(String[] args) • od main rozpoczyna si˛e wykonywanie aplikacji (innym rodzajem tworzonych w Javie programów sa˛ np. aplety – programy działajace ˛ zwykle na stronie WWW, w oknie przegladarki ˛ internetowej) 1. kompilacja do postaci bytecode’u: $ javac MojProgram.java ⇒ wytworzenie pliku MojProgram.class (lub komunikaty o bł˛edach kompilacji!) 2. uruchomienie programu nast˛epuje za pomoca˛ JVM: $ java MojProgram → [MojProgram!] 2 Typy danych • proste (primitive types) int – 32-bitowa liczba całkowita (zakres −231 ÷ 231 − 1) byte – 8-bitowa liczba całkowita (−128 ÷ 127) short – 16-bitowa liczba całkowita (−32768 ÷ 32767) long – 64-bitowa liczba całkowita (zakres −263 ÷ 263 − 1) float – 32-bitowa liczba zmiennoprzecinkowa (precyzja ok. 7 cyfr) double – 64-bitowa liczba zmiennoprzecinkowa (precyzja ok. 15 cyfr) char – 16-bitowy znak kodowany jako Unicode (inaczej niż w C++! – łatwo operować na znakach narodowych itp.) Programowanie obiektowe. Wykład 01 4 boolean – typ logiczny (odpowiednik bool z C++), może przechowywać wartości true lub false – . . . oraz typ void Uwaga: Java wymaga dokładnego przestrzegania zgodności typów, stad ˛ np. do przechowywania wartości rzeczywistych zwykle najwygodniej używać tylko typu double Przykład: nie jest możliwe bezpośrednie (bez rzutowania) podstawienie wartości typu double do zmiennej float: // float fX = 1.2; /* ZLE! */ double dX = 1.2; /* OK */ • zakresy ważności nazw sa˛ ograniczone podobnie jak w C i C++ nawiasami klamrowymi { } • nie jest dozwolone przesłanianie nazw, np. { char w = ’a’; { // char w = ’b’; /* ZLE */ } } • obiekty (instancje klas) – wszystkie dziedzicza˛ po wspólnej, bazowej klasie Object (np. wszystkie maja˛ metod˛e toString()) – sa˛ dost˛epne tylko poprzez referencje – nigdy bezpośrednio! – składaja˛ si˛e z: ∗ pól (danych składowych) ∗ metod (funkcji składowych) – tworzone sa˛ za pomoca˛ operatora new Przykład: (klasa String pełni w Javie podobna˛ rol˛e jak std::string w C++) String s = new String("abc"); System.out.println("napis=[" + s + "]"); → napis=[abc] • Instrukcja: dzi˛eki temu Programowanie obiektowe. Wykład 01 5 String s; tworzy tylko referencj˛e – nie odnosi si˛e ona jeszcze do żadnego obiektu (nie została zainicjalizowana); bł˛edna byłaby wi˛ec wtedy instrukcja: System.out.println("napis=["+s+"]"); (efekt → bład ˛ kompilacji: variable s might not have been initialized) • String (klasa obsługujaca ˛ napisy) jest przykładem jednej z bardzo wielu klas dost˛epnych w bibliotece Javy • dla typów prostych, które same nie sa˛ obiektami, dost˛epne sa˛ klasy obudowujace ˛ (wrappers), np. double x = -0.5; Double obj = new Double(x); System.out.println("obj="+obj); → obj=-0.5 • dla klas obudowujacych ˛ (opakowujacych) ˛ jest używany mechanizm automatycznego opakowywania i rozpakowywania double x = 3.0; Double obj = x / 2.0; double y = obj / 2.0; System.out.println("y="+y); → y=0.75 • swoich odpowiedników wśród typów prostych nie maja˛ klasy służace ˛ do operacji arytmetycznych z duża˛ dokładnościa: ˛ BigInteger – liczby całkowitej dowolnego rozmiaru BigDecimal – liczby ułamkowe z dowolna˛ precyzja˛ pozwalaja˛ one na operacje dost˛epne dla innych typów reprezentujacych ˛ liczby, z tym że zamiast operatorów należy użyć odpowiednich metod 3 Operatory • Java zapewnia standardowy zestaw operatorów dla typów prostych (np. arytmetyczne + - / *, operator przypisania = itd.) Programowanie obiektowe. Wykład 01 6 • dla obiektów maja˛ zastosowanie tylko operatory = == != • operatorów nie można przeładowywać • dodatkowo klasa String pozwala na używanie operatorów + oraz += String s = new String("abc"); String t = new String("def"); System.out.println(s+t); → abcdef • jeżeli wyrażenie rozpoczyna si˛e od obiektu typu String, to nast˛epujace ˛ po operatorze + wyrazy także musza˛ być typu String – w razie potrzeby kompilator b˛edzie si˛e starał znaleźć reprezentacj˛e obiektu lub typu protego w postaci napisu double x=-1.2; String u = "x="+x; System.out.println(u); → x=-1.2 • operator przypisania zastosowany dla obiektów kopiuje referencje! • również operatory porównania == i != w przypadku obiektów porównuja˛ same referencje („adresy”), a nie to, na co one wskazuja˛ (zawartość obiektów)! Przykład: class Znak { char z; } Znak a = new Znak(); Znak b = new Znak(); a.z = ’A’; b.z = ’B’; System.out.println("a="+a.z+" b="+b.z); b = a; System.out.println("a="+a.z+" b="+b.z); a.z = ’C’; System.out.println("a="+a.z+" b="+b.z); → a=A b=B a=A b=A a=C b=C Programowanie obiektowe. Wykład 01 7 Znak a = new Znak(); Znak b = new Znak(); a.z = ’q’; b.z = ’q’; System.out.println(a==b); b=a; System.out.println(a==b); → false true • do porównywania obiektów tworzonych z klas bibliotecznych można posłużyć si˛e metoda˛ equals(), która zwykle porównuje zawartość obiektów String s = new String("abc"); String t = new String("abc"); System.out.println(s==t); System.out.println(s.equals(t)); → false true • operator rzutowania: (typDocelowy) może być używany pomi˛edzy dowolnymi typami prostymi z wyjatkiem ˛ boolean, przy czym jawne rzutowanie jest wymagane tylko gdy istnieje groźba utraty informacji; w przypadku obiektów rzutowanie jest możliwe tylko wewnatrz ˛ jednej „rodziny” (tzn. powiazanych ˛ relacja˛ dziedziczenia) int n = 1; double z = n; //OK //n = z; /* ZLE */ n = (int)(z+1.9); System.out.println("z="+z+" n="+n); → z=1.0 n=2 • brak jest operatora w rodzaju sizeof – w Javie jest on zb˛edny: poszczególne typy maja˛ dobrze zdefiniowane rozmiary (wi˛ec nie ma potrzeby sprawdzania np. liczby bajtów zajmowanych przez zmienna˛ typu int). Programowanie obiektowe. Wykład 01 8 4 Klasy • definicja: class Nazwa { . . . pola, metody . . . } • pola moga˛ być zarówno typów prostych, jak i referencjami do obiektów Przykład: class CA { int i; String s; } • referencje musza˛ zostać zainicjalizowane przed użyciem, np. z wykorzystaniem operatora new w konstruktorze • odniesienie si˛e do składników klasy nast˛epuje poprzez operator . public static void main(String[] args) { CA ca = new CA(); ca.i = 5; ca.s = "to jest CA"; System.out.println( ca.s + ", ca.i = " + ca.i); } → to jest CA, ca.i = 5 • każde pole typu prostego jest domyślnie inicjalizowane wartościa: ˛ – 0 w przypadku typów liczbowych – false dla typu boolean – znakiem o kodzie ’\u0000’ jeśli typem jest char Uwaga: Inicjalizacja taka dotyczy tylko pól (danych składowych) klas! • niezainicjalizowane referencje maja˛ wartość null • pola moga˛ być inicjalizowane równocześnie z deklaracja,˛ np. class CA { int x = 5; } Programowanie obiektowe. Wykład 01 9 lub za pomoca˛ tzw. bloku inicjalizacyjnego: class CA { int x; { x = 5; } } • funkcje można w Javie definiować tylko jako metody wewnatrz ˛ klas class CB { void print(String s) { System.out.println(s); } } class Program { public static void main(String[] args) { String w = "ABC"; CB o = new CB(); o.print(w); } } → ABC • argumenty sa˛ przesyłane do metod poprzez wartość – ale dla obiektów ta˛ wartościa˛ jest referencja! class CA { int x = 5; } class CB { void print(CA c){ System.out.println("x=" + c.x); c.x = 0; } } class Program { public static void main(String[] args) { CA a = new CA(); CB b = new CB(); b.print(a); Programowanie obiektowe. Wykład 01 System.out.println("teraz x=" + a.x); } } → x=5 teraz x=0 ? jaki skutek miałoby użycie poniższej metody zdefiniowanej w klasie CB? void swap(CA a, CA b) { CA t = a; a = b; b = t; } Odpowiedź: żaden! CA w = new CA(); CA v = new CA(); w.x=-1; v.x=2; System.out.println(w.x + " " +v.x); b.swap(v,w); System.out.println(w.x + " " +v.x); → -1 2 -1 2 dla porównania: jeśli do klasy CA dodałoby si˛e metod˛e setX class CA { int x = 5; void setX(CA c) { x = c.x; } } to w klasie CB zdefiniować można nast˛epujac ˛ a˛ metod˛e swap2: void swap2(CA a, CA b) { CA t = new CA(); t.setX(a); a.setX(b); b.setX(t); } 10 Programowanie obiektowe. Wykład 01 11 w.x=-1; v.x=2; System.out.println(w.x + " " +v.x); b.swap2(v,w); System.out.println(w.x + " " +v.x); → -1 2 2 -1 ? Dlaczego tym razem zamiana si˛e powiodła? 4.1 Składowe static • metody static moga˛ być uruchamiane nawet gdy nie istnieja˛ żadne obiekty danej klasy; definiuje si˛e je wewnatrz ˛ klasy class CC { static void print(double x){ System.out.println("x="+x); } } wywołanie nast˛epuje poprzez użycie konstrukcji nazwaKlasy.nazwaMetody() Przykład: CC.print(2.3); → x=2.3 Uwaga: metody static (np. main) nie moga˛ si˛e bezpośrednio odnosić do składowych, które nie sa˛ statyczne! • pola static również nie sa˛ zwiazane ˛ z konkretna˛ instancja˛ klasy; deklaruje si˛e je wewnatrz ˛ klasy i moga˛ być inicjalizowane równocześnie z deklaracja˛ class CD { static int n=0; } CD.n = -3; CC.print(CD.n); Programowanie obiektowe. Wykład 01 12 → x=-3.0 • przykładem statycznego pola jest składnik out klasy System ⇒ dlatego mogliśmy wywoływać dla niego metod˛e println, mimo że nie tworzyliśmy żadnego obiektu klasy System System.out.println( "System.out= " + System.out ); → System.out= java.io.PrintStream@675b7986 4.2 Dostep ˛ do składników • określany znanymi z C++ słowami kluczowymi: – public – protected – private • należy je umieszczać każdorazowo przed polem lub metoda,˛ których maja˛ dotyczyć • w Javie nie ma natomiast możliwości deklarowania klas lub metod zaprzyjaźnionych • brak słów kluczowych private, protected i public skutkuje jeszcze innym, domyślnym sposobem ograniczenia dost˛epu: składnik taki b˛edzie dost˛epny jedynie dla klas z tego samego pakietu (zwykle klas w tym samym pliku i innych plikach z tego samego katalogu), dla innych b˛edzie si˛e zachowywał tak, jakby był typu private ⇒ jest to tzw. dost˛ep pakietowy (package access) • protected umożliwia dost˛ep do składników nie tylko klasom potomnym, ale także innym klasom z tego samego pakietu 4.3 Dostep ˛ do klas i nazwy plików źródłowych • klasy moga˛ być deklarowane jako public (ogólnie dost˛epne) lub bez żadnego modyfikatora (dost˛epne w tym samym pakiecie) • klas˛e publiczna˛ należy umieszczać w pliku o nazwie zgodnej z nazwa˛ klasy; w tym samym pliku moga˛ si˛e znajdować również definicje innych (niepublicznych) klas 5 Klasy biblioteczne • przed użyciem klas dodatkowych (tzn. spoza pakietu java.lang) dost˛epnych z bibliotek Javy (lub własnych pakietów) należy je dołaczyć ˛ korzystajac ˛ z polecenia: import nazwaPakietu.NazwaKlasy ; – lub odnosić si˛e do nich w kodzie poprzez pełna˛ nazw˛e, np. java.util.Vector Programowanie obiektowe. Wykład 01 13 import java.util.Date; class Program { public static void main(String[] args){ Date d = new Date(); System.out.println("Dzisiaj= "+d); } } → Dzisiaj= Wed Feb 27 10:58:16 CEST 2008 • oprócz importowania pojedynczych klas można również dodać cały pakiet, np. w poprzednim przykładzie lini˛e import java.util.Date; można zastapić ˛ instrukcja˛ import java.util.*; • domyślnie dost˛epne sa˛ wszystkie klasy z pakietu java.lang należa˛ do nich m.in.: – String – Math – klasa zawierajaca ˛ podstawowe funkcje matematyczne takie jak np.: sin(double x) sqrt(double x) oraz stałe: E – liczba e PI – liczba π double x = Math.PI; double y; y = Math.cos(x/2); System.out.println("cos(PI/2)="+y); → cos(PI/2)=6.123233995736766E-17 • pełna˛ dokumentacj˛e bibliotek Javy można pobrać do zainstalowania lub przegladać ˛ online na stronach http://java.sun.com/javase/reference/api.jsp (np. dla wersji J2SE 5.0 pod adresem http://java.sun.com/j2se/1.5.0/docs/ api/ a dla Java SE 6 http://java.sun.com/javase/6/docs/api/ ) Programowanie obiektowe. Wykład 01 14 6 Tablice • sa˛ obiektami definiowanymi za pomoca˛ operatora [] typ[] nazwaObiektu; (definiuje si˛e w ten sposób jak zwykle referencj˛e do obiektu! – nie została zarezerwowane jeszcze żadna pami˛eć) • tworzone sa˛ operatorem new int[] t1 = new int[5]; lub jednocześnie z inicjalizacja˛ int[] t2 = {1,2,3}; String[] tab = { new String("abc"), new String("def") }; ? Co byłoby efektem wykonania instrukcji t1=t2; ? • każda tablica posiada pole o nazwie length zawierajace ˛ informacj˛e o jej rozmiarze (poszczególne elementy maja˛ numery od 0 do length-1) for(int i=0;i<tab.length;i++) System.out.print(tab[i]+"|"); for(int i=0;i<t1.length;i++) System.out.print(t1[i]+"#"); for(int i=0;i<t2.length;i++) System.out.print(t2[i]+":"); → abc|def|0#0#0#0#0#1:2:3: • wyjście poza tablic˛e skutkuje natychmiastowym wystapieniem ˛ sytuacji wyjatkowej ˛ java.lang.ArrayIndexOutOfBoundsException • rozmiar tablicy może być obliczany w trakcie wykonywania programu int N = 4; /* ... */ double[] z = new double[N*10]; • utworzenie tablicy dla obiektów tworzy w rzeczywistości tylko tablic˛e referencji – same obiekty też dopiero wymagaja˛ utworzenia za pomoca˛ new! Programowanie obiektowe. Wykład 01 15 class Znak { char z=’x’; } Znak[] ts = new Znak[3]; //System.out.println(ts[1].z); /* ZLE */ for(int i=0;i<ts.length;i++) ts[i] = new Znak(); System.out.println(ts[1].z); →x ⇒ próba dost˛epu do nieutworzonego elementu tablicy kończy si˛e wystapieniem ˛ wyjatku ˛ java.lang.NullPointerException 6.1 Tablice wielowymiarowe • obiektem zawartym w każdym elemencie jednowymiarowej tablicy może być kolejna tablica – łatwo można tworzyć wielowymiarowe tablice, także o różnych rozmiarach poszczególnych „podtablic” (np. tablica dwuwymiarowa o wierszach różnej długości) int[][] t = { {1,2,3}, {4,5} }; for(int i = 0; i < t.length; i++) for(int j = 0; j < t[i].length; j++) System.out.println("t[" + i + "][" + j + "] = " + t[i][j]); → t[0][0] t[0][1] t[0][2] t[1][0] t[1][1] = = = = = 1 2 3 4 5 String[][] ts = new String[2][2]; for(int i = 0; i < ts.length; i++) for(int j = 0; j < ts[i].length; j++) { ts[i][j] = new String("ts"+i+j); System.out.println("ts[" + i + "][" + j + "] = " + ts[i][j]); } → ts[0][0] ts[0][1] ts[1][0] ts[1][1] = = = = ts00 ts01 ts10 ts11 Programowanie obiektowe. Wykład 01 16 6.2 Klasa Arrays • pakiet java.util.* • zbiór statycznych metod do typowych operacji na tablicach (np. wyszukiwanie, sortowanie, porównywanie) int[] t = {4,2,1,3}; Arrays.sort(t); System.out.println(Arrays.toString(t)); → [1, 2, 3, 4] 7 Styl – konwencje, nazewnictwo itp. • najcz˛eściej przyjmowana praktyka to nazywanie klas z dużej litery, a jeśli nazwa składa si˛e z kilku słów to łaczenie ˛ ich w jeden napis, z zaznaczeniem pierwszych znaków dużymi literami, np.: MojaBardzoPotrzebnaKlasa • nazwy metod tworzy si˛e zwykle podobnie, z tym że zaczynajac ˛ od małej litery: pewnaPozytecznaMetoda() • nazwy zmiennych tworzone sa˛ na tej samej zasadzie co nazwy metod; zalecane jest unikanie nazw rozpoczynajacych ˛ si˛e od znaku podkreślenia • stałe maja˛ nazwy pisane samymi dużymi literami, np. Math.PI jeśli składaja˛ si˛e z kilku słów, to rozdziela si˛e je znakiem podkreślenia, np. WAZNA_STALA_MATEMATYCZNA Wi˛ecej zaleceń można znaleźć w dokumencie Code Conventions for the Java Programming Language http://java.sun.com/docs/codeconv/