Wstęp do ćwiczeń
1.1. Program w języku Java
Program w języku Java składa się z klas. Zwykle w jednym pliku jest jedna klasa, której nazwa jest identyczna z nazwą pliku. Zamiast funkcji znanych z języków proceduralnych, w Javie mamy metody. Metoda jest funkcją przypisaną do klasy.
public class Main {
public static void main(String[] args) {
// TODO code application logic here
}
}
W powyższym kodzie pokazano klasę o nazwie Main, która posiada metodę o nazwie main. Program w javie składa się z 1 lub kilku klas. W jednej z nich musi wystąpić metoda main. Jej znaczenie jest identyczne jak funkcji main znanej z języka C. Składnia instrukcji pętli, warunkowej, wyboru w języku java są identyczne jak w języku C.
Wyświetlanie tekstu na konsoli:
System.out.print(”tekst”);
System.out.printf(”%s”, ”tekst”);
1.2. Klasy i obiekty
Klasa jest uogólnieniem pojęcia typu znanego z języka C. Obiekt jest instancją klasy.
HashSet zbior;
zbior = new HashSet();
Powyższy kod deklaruje zmienną o nazwie zbior, która jest typu HashSet. HashSet to nazwa pewnej klasy. Druga linijka tworzy obiekt klasy HashSet i przypisuje referencję do tego obiektu do zmiennej. Referencja jest odpowiednikiem wskaźnika znanego z języka C.
1.3. Dziedziczenie
Klasa może dziedziczyć cechy innej klasy, np. klasy rower i samochód dziedziczą po klasie pojazd. Wszystkie klasy języka java dziedziczą po klasie Object. Dziedziczenie deklarowane jest w momencie tworzenia klasy. Zajmiemy się tym dokładniej na kolejnych zajęciach.
Pojazd pojazd;
Rower rower = new Rower();
Samochód samochod = new Samochód();
pojazd = samochod;
pojazd = rower;
Jeżeli przyjmiemy powyższe założenia o dziedziczeniu klas rower, samochód i pojazd, to kod ten jest poprawny. Do zmiennej pojazd można przypisać referencje do obiektów klasy samochód lub rower, ponieważ obydwa są pojazdami. Do zmiennej klasy Object możemy przypisać referencję do dowolnego obiektu.
1.4. Kolekcje
Kolekcja jest klasą, która pozwala przechowywać obiekty w pewien uporządkowany sposób. Niektóre kolekcje w Javie to:
HashSet zbiór w sensie takim, jaki znany jest z matematyki
ArrayList lista
Chcąc dodać obiekt do kolekcji, używamy metody add().
zbior.add(”A”);
zbior.add(”B”);
Powyższy kod dodaje do kolekcji dwa elementy. Ilość elementów w kolekcji jest ograniczona zasobami systemu operacyjnego.
1.5. Iterator
Iterator jest klasą, która pozwala na dostęp do elementów kolekcji. Obiekty kolekcji posiadają metodę iterator(), która zwraca iterator.
Iterator i;
i = zbior.iterator();
while(i.hasNext()) {
Object o;
o = i.next();
}
W powyższym kodzie zadeklarowana została zmienna i klasy Iterator, do której został przypisany iterator kolekcji. Pętla while przechodzi przez kolejne elementy kolekcji. Metoda next() iteratora zwraca referencję do kolejnego elementu kolekcji.
Dopuszczalne jest również stosowanie niejawnego iteratora:
for(Object element: zbior) {
System.out.println(element.toString());
}
W kodzie powyżej użyto pętli for w celu uzyskania dostępu do wszystkich elementów zbioru. Zmienna o nazwie zbiormusi być kolekcją. Wewnątrz pętli zmiennej element przypisywane są kolejne elementy zbioru.
1.6. Wczytywanie danych tekstowych z pliku
Używamy klasy Scanner i wyrażeń regularnych.
Scanner s;
s = new Scanner(new BufferedReader(new FileReader("plik.txt")));
while (s.hasNext(”wyrażenie regularne”)) {
String linia = s.next(”wyrażenie regularne”);
System.out.println(linia);
}
Pierwsza linijka deklaruje zmienną s klasy Scanner, druga tworzy skaner pliku o podanej nazwie. W pętli whileposzukujemy linii pasujących do wyrażenia regularnego, zapisujemy je do zmiennej linia i wyświetlamy je. Wyrażenie regularne określone jest w kolejnym punkcie instrukcji.
1.7. Wyrażenia regularne
Utworzymy wyrażenie regularne opisujące jedną linię pliku z danymi. W każdej linii jest zapisana informacja o zbiorze. Każda linia zaczyna się i kończy nawiasem klamerkowym:
\{ tutaj są elementy zbioru oddzielone przecinkami \}
Elementem zbioru jest ciąg 1 lub wielu znaków alfanumerycznych (to wyrażenie opisuje zbiór jednoelementowy):
\{\p{Alnum}+\}
Zbiór musi zawierać przynajmniej 1 element, po nim mogą wystąpić kolejne elementy. Kolejne elementy oddzielone są od siebie przecinkami:
\{(\p{Alnum}+)(,\p{Alnum}+)*\}
Po przecinku, przed i za nawiasami może być dowolna ilość spacji lub tabulatorów (może ich też nie być):
\s*\{\s*(\p{Alnum}+)(,\s*\p{Alnum}+)*\s*\}\s*
Należy pamiętać, że w języku Java, identycznie jak w językach C i C++, chcąc uzyskać znak \ w łańcuch tekstowym, należy wpisać \\. Wyrażenie regularne przypisane do zmiennej tekstowej wyglądałoby więc następująco:
String wr = ”\\s*\\{\\s*(\\p{Alnum}+)(,\\s*\\p{Alnum}+)*\\s*\\}\\s*”;
1.8. Skaner łańcucha tekstowego
Klasa Scanner może być użyta również do pobierania sformatowanych danych tekstowych z łańcuchów tekstowych (zmiennych klasy String). Chcąc utworzyć skaner łańcucha tekstowego, używamy instrukcji:
skaner2 = new Scanner(”tekst”);
Instrukcja:
skaner2.useDelimiter(",");
ustawia przecinek jako separator pól.
1.9. Operacje na łańcuchach tekstowych
W celu przeprowadzania operacji na tekście, używamy metod klasy String np.:
int dlugoscLinii = linia.length();
linia = linia.substring(1, dlugoscLinii – 1);
linia = linia.trim();
Pierwsza linijka wyznacza ilość znaków w zmiennej linia, która jest klasy String. Druga usuwa z linii pierwszy i ostatni znak. Trzecia usuwa początkowe i końcowe spacje z linii.
***********************************
1. Paradygmat programowania obiektowego
Zgodnie z paradygmatem programowania obiektowego, program jest zbiorem obiektów komunikujących się między sobą w określony sposób. Każdy obiekt posiada pewien stan (dane charakteryzujące obiekt) i zachowanie (metody przetwarzające dane). Zbiór obiektów posiadających identyczne cechy tworzy klasę. Klasy mogą posiadać powiązania strukturalne między sobą.
Spośród obiektów tworzących program, wyróżniamy 3 grupy:
1.Obiekty warstwy danych.
2.Obiekty warstwy logiki.
3.Obiekty warstwy prezentacji.
1.1. Obiekty warstwy danych
Obiekty te odpowiadają strukturom danych z języka C i ich zastosowanie jest identyczne, jak w przypadku struktur. Pomiędzy obiektami występują zwykle zależności strukturalne (związki). Rozpatrzmy np. klasy obiektów płyta CD i utwór na płycie CD. Po polsku powiemy, że:
na jednej płycie CD znajduje się wiele utworów,
dany utwór przypisany jest do konkretnej płyty CD.
Używając języka Java zapiszemy:
public class Utwor { //tutaj pola z danymi o utworze PlytaCD plyta; } | public class PlytaCD { //tutaj pola z danymi o płycie List<Utwor> utwory; } |
Dostęp do danych charakteryzujących obiekt powinien odbywać się przy użyciu metod. Dla klasy Utwor mamy:
public class Utwor {
private Wykonawca wykonawca;
private Time czasTrwania;
private PlytaCD plyta;
public Wykonawca getWykonawca() {return wykonawca;}
public void setWykonawca(Wykonawca w) {wykonawca = w;}
// pozostałe metody get i set
}
Należy dokładnie przemyśleć potrzebę dodania innych metod niż get i set do obiektów warstwy danych. Zwykle ich obecność jest błędem logicznym. Np. metoda odtworz() w obiekcie klasy Utwor wydaje się poprawna, bo jej zadaniem jest odtworzenie tego konkretnego utworu. Jednak ścieżka na płycie CD sama się nie odtwarza, potrzebne jest urządzenie potrafiące prezentować muzykę.
1.2. Obiekty warstwy logiki
Zadaniem tych obiektów jest realizacja algorytmów przetwarzających dane modelowane przez warstwę danych. W przykładzie z płytą CD i utworami, można utworzyć klasę obiektów SystemCDPlayer, której zadaniem jest przetwarzanie danych z płyt CD:
public class SystemCDPlayer {
private PlytaCD plyta;
//tutaj inne pola potrzebne systemowi do pracy
public void setPlytaCD(PlytaCD p) {plyta = p;}
public PlytaCD getPlytaCD() {return plyta;}
public void play(int sciezka) {. . .}
public MP3 createMP3(int sciezka) {. . .}
//tutaj pozostałe metody
}
Pomiędzy warstwą logiki i warstwą danych nie ma zależności strukturalnych. Powiemy, że SystemCDPlayer używa płyty CD, w celu odtworzenia jej utworów. Stwierdzenie, że system jest związany z pewną płytą CD lub utworem nie jest prawdziwe.
Obiekty warstwy logiki muszą być wyspecjalizowane w realizacji jednej funkcjonalności. SystemCDPlayer nie potrafi obsługiwać przycisków, wyświetlacza, głośnika urządzenia. Zawiera kod, który np. przetwarza dane z postaci zapisanej na ścieżce CD na postać akceptowalną przez obiekt klasy Głośnik.
1.3. Obiekty warstwy prezentacji
Bardzo często mamy do czynienia z sytuacją, że dane po przetworzeniu przez warstwę logiki powinny być przedstawione w pewien sposób. Zadanie prezentacji danych wykonują specjalizowane obiekty. Są one interfejsem pomiędzy klientem programu (użytkownikiem, innym programem), a warstwą logiki. W przykładzie z płytą CD i utworami, można utworzyć klasę obiektów CDPlayer, której zadaniem jest obsługa przycisków i wyświetlacza urządzenia. Klasa ta używa klasy SystemCDPlayer w celu realizacji funkcji poszczególnych przycisków.
***********************************