Podstawy języka, cd
(programowanie obiektowe)
Krystian Ignasiak
K.Ignasiak@ire.pw.edu.pl
http://tiger.ire.pw.edu.pl/proze
Obsługa błędów
• Błędom nie sposób zapobiec…
• Błędy można obsłużyć (naprawić, zareagować
na nie…)
– W metodzie, w której je wykryto
– W metodzie, która wywołała metodę, w której je
– W metodzie, która wywołała metodę, w której je
wykryto:
• Zwracana wartość szczególna (np. 0, -1…)
• Zwracana wartość szczególna i ustawiana zmienna
globalna (np.
errno
)
• WYJĄTEK
Co to jest wyjątek ?
• Sytuacja nadzwyczajna, niezwykła,
wymagająca przywrócenia zwykłego stanu
programu
– Próba usunięcia nieistniejącego pliku
– Przekroczenie zakresu (indeksu) tablicy
– Przekroczenie zakresu (indeksu) tablicy
– Dzielenie przez zero, itp.
• Wyjątek jest obiektem klasy dziedziczącej po
klasie
java.lang.Throwable
• Dwie podklasy
– java.lang.Exception
– java.lang.Error
Obsługa wyjątków
• Unchecked (niekontrolowane,
nieweryfikowane)
– Ich klasy dziedziczą po:
java.lang.Error
i
java.lang.RuntimeException
– Nie muszą być jawnie złapane (obsłużone)
– Nie muszą być jawnie złapane (obsłużone)
• Zwykle nawet nie powinny być obsługiwane
• Efektywność
• Checked (kontrolowane, weryfikowane)
– Wszystkie pozostałe…
– Muszą być gdzieś obsłużone
Hierarchia wyjątków
try – catch – finally
try {
// kod niebezpieczny
} catch(TypWyj
ą
tku1 id1) {
// obsługa wyj
ą
tków typu 1
} catch(TypWyj
ą
tku2 id2) {
} catch(TypWyj
ą
tku2 id2) {
// obsługa wyj
ą
tków typu 2
} catch(TypWyj
ą
tku3 id3) {
// obsługa wyj
ą
tków typu 3
} finally {
// czynno
ś
ci wykonywane zawsze
}
Wyjątki – przykład
int count = 0;
while (true) {
try {
if (count++ == 0) {
throw new ThreeException();
}
System.out.println("bez wyj
ą
tku");
System.out.println("bez wyj
ą
tku");
} catch (ThreeException e) {
System.err.println("ThreeException");
} finally {
System.err.println("zawsze");
if (count == 2) {
break;
}
}
}
Programowanie obiektowe (1)
• Pojęcia, zasady (czasem nazywane
paradygmatami)
– Klasa, obiekt
– Abstrakcja
– Kapsułkowanie (enkapsulacja, hermetyzacja,
– Kapsułkowanie (enkapsulacja, hermetyzacja,
ukrywanie)
– Dziedziczenie (rozszerzanie, generalizacja)
– Polimorfizm
Programowanie obiektowe (2)
• Programowanie proceduralne:
– Program jako zbiór procedur (funkcji)
realizujących określone zadania
– Brak wyraźnego – na pierwszy rzut oka –
powiązania pomiędzy funkcjami a danymi, z
których korzysta program
których korzysta program
• Programowanie obiektowe
– Program jako zbiór dynamicznie tworzonych
obiektów, które ze sobą współpracują
– Wyraźna zależność pomiędzy danymi
przechowywanymi w obiektach i metodach
manipulujących nimi
Programowanie obiektowe (3)
• Obiektowa analiza, projektowanie i programowanie
opierają się na naturalnych dla człowieka
mechanizmach
– Postrzeganie otaczającego świata jako zbiór obiektów:
człowiek, zwierzę, roślina, przedmiot…
• Nieustanna klasyfikacja obiektów
• Nieustanna klasyfikacja obiektów
– Łączenie w grupy, często hierarchicznie, na podstawie
zauważonych podobieństw
• Klasyfikacja wg zmiennych zasad, zależnie od
przyjętych w danej chwili kryteriów
– Zbiór artykułów gospodarstwa domowego, można
podzielić w różny sposób na grupy, raz wg wagi
przedmiotu, a innym razem wg zastosowania, wymiarów,
materiału z którego zostały zrobione, kolorystyki itd.
Programowanie obiektowe (4)
• Główne zalety
– Zwiększenie przejrzystości kodu źródłowego –
staje się on bardziej zrozumiały i lepiej oddaje
logikę tworzonych programów
– Ułatwia i przyspiesza proces tworzenia aplikacji
– Ułatwia i przyspiesza proces tworzenia aplikacji
• Możliwość powtórnego użycia (reuse) gotowych – i co
ważniejsze – sprawdzonych komponentów
• Tworzenie programu w języku obiektowym
(C++, Java…) nie jest jeszcze równoznaczne
z programowaniem obiektowym...
Pojęcie obiektu i klasy (1)
• Rzeczywisty obiekt zwykle jest rozumiany jako coś
materialnego
– Przykłady: drzewo, kamień, kałuża, pies, koń, ręka...
• Obiekt w programowaniu obiektowym to element,
którego istnienie jest logicznie uzasadnione i ma
określone znaczenie w modelu zastosowanym do
oprogramowania konkretnego problemu
– Obiektem może być wszystko co tylko daje się opisać i
przedstawić w postaci zbioru określonych cech (dane) i
zachowań (metody)
– Obiekt może – lecz nie musi – mieć swój rzeczywisty (tj.
materialny) odpowiednik
Pojęcie obiektu i klasy (2)
• Obiekt ma następujące cechy:
– Struktura – ilość i rodzaj informacji
przechowywanych w obiekcie
– Stan – aktualna zawartość atrybutów obiektu
– Tożsamość – każdy obiekt daje się jednoznacznie
zidentyfikować oraz odróżnić od innych obiektów
zidentyfikować oraz odróżnić od innych obiektów
• Jeśli dwa obiekty są tej samej klasy i przechowują (w
danej chwili) dokładnie te same dane, to różnią się co
najmniej lokalizacją w pamięci komputera
– Zachowanie – czyli zbiór metod operujących na
obiekcie, jednakowy dla wszystkich obiektów w
ramach danej klasy
Pojęcie obiektu i klasy (3)
• Klasa – to wzorzec obiektów, szablon przy pomocy
którego tworzone są nowe obiekty; klasa określa
zbiór danych i metod, które będą mieć powstałe na
jej podstawie obiekty
• Intuicje:
– Foremki do ciastek; jedna foremka, czyli klasa = wiele
podobnych lub nawet jednakowych ciastek, czyli
obiektów
– Zapiszmy „definicję” książki:
• dokument z jakąś treścią, tytułem, autorem, określoną liczbą stron
weźmy do ręki dwie książki: książki są obiektami, a
zapisana definicja – klasą, czyli opisem ich
najważniejszych cech
Abstrakcja (1)
• Klasa nie musi uwzględniać wszystkich szczegółów
obiektów, powinna skupiać się na cechach istotnych
z punktu widzenia aplikacji
– Baza danych studentów na potrzeby uczelni nie musi w
obiektach klasy Student przechowywać wszystkich
możliwych informacji o studencie (obwód w pasie, numer
możliwych informacji o studencie (obwód w pasie, numer
buta, poziom cukru we krwi, liczba wypalanych
papierosów dziennie, liczba włosów na głowie...)
– Prawdopodobnie wystarczy imię, nazwisko, numer
indeksu, adres, lista ocen...
– Umawiamy się, że klasa Student opisuje tylko istotne
cechy studenta
Abstrakcja (2)
• Abstrakcja może być rozpatrywana również
w kontekście zachowań przypisanych do
danych klas (obiektów)
• Korzystanie z obiektu nie wymaga pełnej
wiedzy na temat sposobu, w który zostały
wiedzy na temat sposobu, w który zostały
zaimplementowane jego metody – zatem
abstrahujemy od szczegółów
implementacyjnych, a skupiamy się na
przeznaczeniu obiektu, na sposobie w jaki
można użyć obiektu w programie
Kapsułkowanie (1)
• Ukrywanie pewnych szczegółów
implementacyjnych, danych i metod obiektu
• Ukrywanie przed kim ? przed czym ?
– Czasem przed innymi programistami, którzy będą
korzystać z przygotowanych przez nas klas i obiektów, a
czasem przed pozostałymi elementami tej samej aplikacji
czasem przed pozostałymi elementami tej samej aplikacji
• Ułatwia podział pracy i pracę zespołową
– Graficy przygotowujący szatę graficzną dla sklepu
internetowego wcale nie muszą wiedzieć jakich
algorytmów używamy np. do obliczania rabatu, interesuje
ich tylko jak można odczytać wartość rabatu dla
konkretnego produktu i jak ją wyświetlić na stronie
WWW (interfejs)
Kapsułkowanie (2)
• Jesteśmy przyzwyczajeni do tego, że do obsługi
czasem bardzo skomplikowanych urządzeń (jak np.
telewizor, magnetowid) wystarczy krótka instrukcja
i np. pilot
• Nie potrzebna jest nam wiedza na temat konstrukcji
telewizora, ważne aby się włączał, wyłączał,
zmieniał kanały, zmieniał poziom głośności itd.
• Uproszczenie obsługi, ograniczenie liczby
dostępnych funkcji do niezbędnego minimum – te
czynniki zmniejszają ryzyko nieumyślnego zepsucia
urządzenia – to samo dotyczy tworzonego przez nas
oprogramowania !
Kapsułkowanie (3)
• Brak kapsułkowania
• Po zastosowaniu kapsułkowania
Kapsułkowanie (4)
• Ma również sens w przypadku gdy całą aplikację
tworzy jeden programista:
– Umożliwia późniejsze wykorzystanie gotowych i
przetestowanych elementów w innych programach
– Zmniejsza ryzyko popełnienia błędu przy aktualizacji
danych przechowywanych w obiekcie
danych przechowywanych w obiekcie
– Przykład: klasa KontoBankowe, z polami: stanKonta oraz
dostępneŚrodki, gdzie dostępneŚrodki = stanKonta + limit
kredytu; zmiana wartości pól stanKonta i dostępneŚrodki
musi odbywać się równocześnie ! dostępneŚrodki nie
mogą być wartością ujemną, przed czym również
zabezpieczy kapsułkowanie !
Kontrola dostępu
Modyfikator
TA
klasa
TEN
pakiet
Klasa
pochodna
Ś
wiat
zewnętrzny
public
+
+
+
+
protected
+
+
+
protected
+
+
+
–
+
+
private
+
Klasa w Javie
• Jest definicją typu danych
• class NazwaTypu { /*
definicja
*/ }
• NazwaTypu nt = new NazwaTypu();
• Pola, atrybuty (fields, attributes)
– class Dane {
– class Dane {
int a;
float b;
}
• Metody (methods, member functions)
– class Metody {
void metodaA(int b) { /*
definicja
*/ }
float metodaB(float f) { /*
definicja
*/ }
}
Cykl życia obiektów
• Obiekty tworzone są przy pomocy operatora
new
, którego argumentem jest nazwa klasy
• Cykl:
– Przydział pamięci
– Inicjalizacja (konstruktor)
– Inicjalizacja (konstruktor)
– Użycie (używanie) obiektu
– Zwolnienie pamięci
• W Javie nie dysponujemy niczym o
własnościach destruktora (w terminach C++),
którego należałoby użyć w parze w
konstruktorem
Przebieg inicjalizacji (1)
1. Przy pierwszym użyciu klasy, interpreter
lokalizuje plik z kodem klasy (.class) na
ś
cieżce ustawionej w zmiennej systemowej
CLASSPATH
2. Interpreter tworzy obiekt klasy
Class
,
2. Interpreter tworzy obiekt klasy
Class
,
opisujący ładowaną klasę i wykonuje
inicjalizacje statyczne
3. Kiedy tworzymy obiekt, interpreter
przydziela pamięć potrzebną do
przechowania atrybutów
Przebieg inicjalizacji (2)
4. Przydzielona pamięć jest zerowana, co
odpowiada domyślnym wartościom
atrybutów (zerowanie)
5. Jeśli definicja klasy przewiduje jawną
inicjalizację atrybutów – jest ona
inicjalizację atrybutów – jest ona
wykonywana
6. Wołany jest konstruktor
Inicjalizator statyczny
• Umożliwia wykonanie pewnych (statycznych)
czynności inicjalizujących w momencie ładowania
kodu klasy
• class Thing {
static private int counter;
static {
static {
counter = 0;
}
public static int getCounter() {
return counter;
}
public Thing() { counter++; }
}
Domyślna inicjalizacja atrybutów
• Pamięć przydzielona obiektowi jest zerowana, co
odpowiada ustaleniu następujących wartości
atrybutów dla poszczególnych typów danych:
– boolean: false
– char: ’\u0000’
– byte: (byte)0
– short: (short)0
– int: 0
– long: 0L
– float: 0.0f
– double: 0.0d
– referencje:
null
Konstruktor
• Specjalna metoda, o nazwie identycznej z
nazwą klasy
• Konstruktor nie ma typu
• class Thing {
private int x;
private int x;
Thing() { x = 12; }
Thing(int xx) { x = xx; }
}
• Konstruktor jest wołany po przydzieleniu
pamięci na obiekt i po zainicjowaniu pól
Konstruktor domyślny (default)
• Każda klasa ma zawsze co najmniej jeden
konstruktor
• Jeśli nie dostarczymy żadnego konstruktora,
kompilator wygeneruje konstruktor domyślny (bez
parametrów), jak w przykładzie:
– class Thing {
private int x;
}
– Równoważne:
class Thing {
private int x;
Thing() {}
}
Inicjalizacja – przykład
class Thing {
static int a = 8;
int b;
int c = 19;
Thing() { b = 33; }
Thing() { b = 33; }
}
Thing t = new Thing();
Obiekty osiągalne
Zbiór
referencji
głównych
Osi
ą
gal
ne
Nieosi
ą
galne
Sterta
Odzyskiwanie nieużywanej pamięci
• Garbage collection
– Maszyna wirtualna utrzymuje tablicę referencji
do obiektów, np. licznik referencji
• Gdy obiekt jest nieosiągalny może zostać
usunięty z pamięci
usunięty z pamięci
– r = null;
– Wyjście z bloku, itp.
• Metoda
finalize()
– wołana, gdy
maszyna wirtualna zdecyduje się zwolnić
pamięć zajmowaną przez obiekt
Reguły finalizacji obiektów
• Obiekt może nigdy nie zostać usunięty
• Nie należy traktować finalizacji jak destrukcji
obiektu (w terminach C++)
• Proces garbage collection dotyczy tylko
odzysku nieużywanej pamięci
odzysku nieużywanej pamięci
• Funkcja
System.gc()
• Wyjątki zgłoszone w ramach
finalize()
są pozostawiane bez obsługi – zatrzymują
jednak proces finalizacji tego obiektu
this
• Specjalna referencja (w metodach) na aktualny
obiekt (na rzecz którego wywołano metodę)
• W innym użyciu – odwołanie do innego
konstruktora
• class Klasa {
private int x;
Klasa() { x = 5; }
Klasa() { x = 5; }
Klasa(int x) { this.x = x; }
Klasa(double x) { this((int) x); }
Klasa increment() {
x++;
return this;
}
}
• this
nie jest dostępne w metodach statycznych
(funkcjach)
Metody statyczne (funkcje)
• Istnieją (tj. można się do nich odwołać)
pomimo braku instancji obiektu danej klasy
• class Leaf {
static void f() { ... }
}
}
Leaf.f();
Przykład – singleton
• Singleton to wzorzec programistyczny klasy
umożliwiającej utworzenie tylko jednego
obiektu tej klasy
• public class Singleton {
private static final Singleton
private static final Singleton
instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
Przekazywanie przez wartość
• W Javie jedynym sposobem przekazywania
argumentów jest przekazywanie przez wartość
(argument nie może być zmodyfikowany w
metodzie)
• Jednak jeśli argumentem jakiejś metody jest obiekt,
referencja
to argumentem tym jest referencja do tego obiektu,
także przekazywana przez wartość
• Wynika z tego, że zawartość obiektu może być
zmodyfikowana wewnątrz metody, która otrzymuje
referencję, lecz sama referencja nie może być
zmodyfikowana
Kontrola dostępu
Modyfikator
TA
klasa
TEN
pakiet
Klasa
pochodna
Ś
wiat
zewnętrzny
public
+
+
+
+
protected
+
+
+
protected
+
+
+
–
+
+
private
+
Dziedziczenie (1)
• Dziedziczenie (rozszerzanie, generalizacja,
inheritance) to tworzenie nowej klasy na
bazie już istniejącej
– Klasa nadrzędna (bazowa, podstawowa, nadklasa,
superclass)
superclass)
– Klasa dziedzicząca (podrzędna, pochodna,
rozszerzająca, podklasa, subclass)
• Dziedziczy pola i metody klasy bazowej
• Może mieć dodatkowe pola i metody w stosunku do
klasy bazowej (rozszerzać listę atrybutów i metod)
• Może przedefiniowywać metody z klasy bazowej
(przesłanianie)
Dziedziczenie (2)
• Klasa Osoba oraz dwie klasy pochodne:
Student i Nauczyciel; diagram UML:
Osoba
+ imi
ę
: String
+ nazwisko : String
• Klasy Student i Nauczyciel dziedziczą pola
imię i nazwisko z klasy Osoba; wnoszą też
własne atrybuty – czyli rozszerzają wiedzę o
obiektach tych klas
Nauczyciel
Student
+ numerIndeksu : int
+ tytułNaukowy : String
Dziedziczenie – przykład (1)
• public class Employee {
public String name = "";
public double salary;
public Date birthDate;
public String getDetails() {...}
}
}
• public class Manager {
public String name = "";
public double salary;
public Date birthDate;
public String department;
public String getDetails() {...}
}
Dziedziczenie – przykład (2)
• public class Employee {
public String name = "";
public double salary;
public Date birthDate;
public String getDetails() {
...
...
}
}
• public class Manager
extends Employee {
public String department;
}
Zasady dziedziczenia w Javie
• Dziedziczenie jednokrotne
• Podklasa dziedziczy wszystkie pola i metody
z nadklasy (z wyjątkiem elementów
prywatnych)
• Podklasa nie dziedziczy konstruktorów z
• Podklasa nie dziedziczy konstruktorów z
klasy bazowej (mimo, ze w procesie
inicjalizacji konstruktory klasy bazowej są
wołane)
Polimorfizm
• Zdolność posiadania wielu różnych form
– Referencja jest polimorficzna
– Wywołania metod w Javie są zawsze
polimorficzne !
• Obiekt ma tylko jedną postać (formę)
• Obiekt ma tylko jedną postać (formę)
– Obiekt nigdy nie jest polimorficzny !
• Referencja może wskazywać na różne obiekty
(obiekty różnych typów):
Employee m = new Manager();
...
m = new Employee();
Polimorfizm – przykład
• public class Employee {
public String getDetails() {
return "Employee:" + name + ... ;
}
}
• public class Manager
• public class Manager
extends Employee {
public String department;
public String getDetails() {
return "Manager:" + name + ... ;
}
}
Operator
instanceof
• public class Employee
extends Object
public class Manager extends Employee
public class Engineer extends Employee
• public void doSomething(Employee e) {
if
(e instanceof Manager) {
// obsługa obiektu Manager
// obsługa obiektu Manager
} else if (e instanceof Engineer) {
// obsługa obiektu Engineer
} else
{ // obsługa obiektu Employee lub
// obiektów innych klas pochodnych
// od klasy Employee
}
}
Rzutowanie referencji
• public void doSomething(Employee e){
if (e instanceof Manager) {
Manager m = (Manager) e;
System.out.println(
”Manager of ” + m.getDepartment());
}
}
...
}
• Wyjątek
ClassCastException
Przeciążanie metod (overloading)
• Możliwość definiowania metod o
identycznych nazwach ...
• ... ale o różnych listach argumentów
• class Thing {
void f() { ... }
void f() { ... }
void f(int a) { ... }
void f(char x) { ... }
float f(float f) { ... }
void f(float f) { ... } //
ź
le...
}
• Konstruktory także mogą być przeciążane
Kontrola dostępu
Modyfikator
TA
klasa
TEN
pakiet
Klasa
pochodna
Ś
wiat
zewnętrzny
public
+
+
+
+
protected
+
+
+
protected
+
+
+
–
+
+
private
+