koniec

Transkrypt

koniec
Programowanie obiektowe
Języki i paradygmaty programowania
Dariusz Wardowski
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
1/21
Programowanie obiektowe
Języki i paradygmaty programowania
Konstruktory w Javie
Konstruktory definiują początkowy stan obiektów. W języku Java również możliwe jest
przeładowanie konstruktorów. Poniżej przedstawiono przykłady:
GregorianCalendar dataDzisiejsza = new GregorianCalendar();
GregorianCalendar data = new GregorianCalendar(2010, Calendar.NOVEMBER, 28);
Gdy w konstruktorze nie ma zainicjalizowanych wartości składowych klasy, wówczas zostają
im nadane wartości domyślne (w C++ ten mechanizm nie występuje!):
-Dla liczb – wartośd zero
-Dla wartości logicznych – false
-Dla referencji – null
W przypadku, gdy klasa nie posiada zdefiniowanych konstruktorów, definiowany jest
konstruktor domyślny, który nadaje wszystkim zmiennym składowym wartości domyślne.
W Javie możliwa jest bezpośrednia inicjalizacja pól składowych klasy (Uwaga w C++ nie!)
class Przykladowa
{
String skladowa = „wartosc domyslna”;
}
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
2/21
Programowanie obiektowe
Języki i paradygmaty programowania
Konstruktory w Javie c.d.
W definicji konstruktora możliwe jest wywołanie innego konstruktora tej samej klasy. Patrz
przykład poniżej.
class Prostokat
{
private int a;
private int b;
public Prostokat(int _a, int _b)
{
a = _a;
b = _b;
}
public Prostokat(int x)
{
this(x,x);
}
}
Gdy tworzony jest obiekt Prostokat p = new Prostokat(10), wówczas konstruktor
Prostokat(int) wywołuje konstruktor Prostokat(int,int).
Użycie w konstruktorze składni this(…), w celu wywołania innego konstruktora, musi wystąpid
jako pierwsze polecenie tego konstruktora. (W C++ niemożliwe jest wywołanie jednego
konstruktora przez drugi).
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
3/21
Programowanie obiektowe
Języki i paradygmaty programowania
Bloki inicjalizacji w Javie
W języku Java istnieje jeszcze inny mechanizm nadawania zmiennym składowych klasy
początkowych wartości za pomocą tzw. bloków inicjalizacji. Instrukcje zawarte w takich
blokach wykonywane są za każdym razem, gdy tworzony jest obiekt.
class Prostokat
{
private int a;
private int b;
public Prostokat(int _a, int _b)
{
a = _a;
b = _b;
}
public Prostokat(int x)
{
this(x,x);
}
{
a = 10;
b = 20;
}
}
Bloków inicjalizacji można użyd np. do inicjalizacji pola statycznego (tzn. pole wspólne dla
wszystkich obiektów tej samej klasy).
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
4/21
Programowanie obiektowe
Języki i paradygmaty programowania
Niszczenie obiektów w Javie
Język Java obsługuje automatyczne usuwanie pamięci przy pomocy tzw. garbage collector.
Język Java nie obsługuje destruktorów. Do każdej klasy można dodad metodę finalize, która
zostanie wywołana przed zniszczeniem obiektu, jest to metoda zanegowana (deprecated).
public class A
{
private int x;
public A(int x)
{
this.x = x;
}
public void finalize(int x)
{
System.out.println(„Zaraz obiekt zostanie zniszczony”);
}
public static void main(String[] args)
{
A a = new A(10);
System.runFinalizersOnExit(true);
}
}
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
5/21
Programowanie obiektowe
Języki i paradygmaty programowania
this
Wszystkie funkcje składowe klasy posiadają wskaźnik this, który wskazuje na obiekt
wywołujący. Zobacz przykłady poniżej.
C++
java
class A
{
private:
int x;
public class A
{
private int x;
public A(int _x)
{
x = _x;
}
public:
A(int _x)
{
x = _x;
}
A podwoj()
{
x *= 2;
return *this;
}
A podwoj()
{
x *= 2;
return this;
}
};
};
W C++ do zwrócenia samego obiektu użyjemy *this (operator wyłuskania), natomiast w
języku Java this jest referencją obiektu.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
6/21
Programowanie obiektowe
Języki i paradygmaty programowania
Zastosowanie klas do typów abstrakcyjnych
Poniżej przedstawiono deklaracje klas, które realizują mechanizm do przechowywania
danych, w których dane są zawsze dodawane lub usuwane ze szczytu stosu.
class Element
{
private:
int x;
Element* next;
public:
Element(int _x);
int getx();
Element* getnext();
void setnext(Element* n);
class Stos
{
private:
Element* top;
public:
Stos();
void push(Element& e);
Element* pop();
};
};
Zastosowanie powyższych klas
int main()
{
Stos s;
Element e1(10); s.push(e1);
Element e2(20); s.push(e2);
Element e3(30); s.push(e3);
while (Element* tmp = s.pop())
cout << tmp->get() << endl;
return 0;
}
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
7/21
Programowanie obiektowe
Języki i paradygmaty programowania
Przeciążanie operatorów (C++)
Technika przeciążania operatorów to pomysł rozszerzenia przeciążania funkcji na operatory.
Czyli standardowym operatorom z C++ można przypisad inne znaczenie. C++ udostępnia
mechanizm przeciążania operatorów dla typów niestandardowych np. obiektów klasy.
Dzięki przeciążaniu operatorów kod wygląda przejrzyście.
Aby przeciążyd operator OP (OP oznacza dowolny operator np. +) należy użyd tzw. funkcji
operatora postaci:
operatorOP(argumenty)
Załóżmy, że w klasie A zdefiniowano metodę operator+(), w ten sposób przeciążono
operator dodawania, możliwe jest zatem dodanie dwóch obiektów klasy A.
A
A
A
c
a = new A();
b = new A();
c;
= a + b;
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
8/21
Programowanie obiektowe
Języki i paradygmaty programowania
Przeciążanie operatorów (C++) - przykład
class Z
{
private:
double Re, Im;
public:
Z(double _Re, double _Im) {Re = _Re; Im = _Im;}
Z(){}
Z operator+(Z & x);
Z operator*(double n);
};
Z Z::operator+(Z & x)
{
Z w;
w.Re = Re + x.Re;
w.Im = Im + x.Im;
return w;
}
Z Z::operator*(double n)
{
Z w;
w.Re = n*Re; w.Im = n*Im;
return w;
}
int main()
{
Z x(1,2);
Z y(-1,3);
Z w1 = x + y;
Z w2 = x*2;
return 0;
}
//Z w2 = 2*x --źle
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
9/21
Programowanie obiektowe
Języki i paradygmaty programowania
Przeciążanie operatorów - ograniczenia
•
•
•
•
•
•
Przynajmniej jeden z argumentów musi byd zdefiniowany przez użytkownika.
Nie można przeciążyd operatora tak aby naruszał zasady składniowe stosowane podczas
używania oryginalnego znaczenia operatora.
Nie można zmienid priorytetu operatorów.
Nie można tworzyd nowych symboli operatorów.
Operatory =, (), [], -> można przeciążad wyłącznie w metodach klasy.
Następujące operatory mogą byd przeciążone:
+
-
*
/
%
^&
|
~=
*=
!
=
<
>
+=
-=
/=
>>=
%=
^=
&=
\=
<<
>>
<<=
++
==
!=
<=
>=
&&
||
delete
,
->*
->
()
[]
new
new[]
delete[]
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
10/21
Programowanie obiektowe
Języki i paradygmaty programowania
Funkcje zaprzyjaźnione
Funkcja zaprzyjaźniona z daną klasą ma takie same przywileje jak metoda tej klasy, w
szczególności ma dostęp do pól prywatnych tej klasy.
Prototyp funkcji zaprzyjaźnionej:
friend typZwracany operatorOP(argumenty);
W części implementacyjnej słowo friend pomijamy.
class Z
{
…
public:
int main()
{
Z z1(1,2);
…
friend Z operator*(double n, Z & z);
Z z2 = z1*2;
Z z3 = 3*z1; //poprawnie
};
return 0;
Z operator*(double n, Z & z)
{
Z w;
w.Re = z.Re * n;
w.Im = z.Im * n;
return w;
}
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
}
11/21
Programowanie obiektowe
Języki i paradygmaty programowania
Przeciążenie operatora <<
W częsci deklaracyjnej klasy:
friend void operator<<(ostream & os, const Z & z);
Definicja:
void operator<<(ostream & os, const Z & z)
{
os << z.Re << „+” << z.Im <<„I”;
}
Użycie opeatora <<
Z z1(2,3);
cout << z1;
Czy zadziała?
Z z1(2,3);
Z z2(3,4);
cout << z1 << z2;
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
12/21
Programowanie obiektowe
Języki i paradygmaty programowania
Przeciążenie operatora << cd.
W częsci deklaracyjnej klasy:
friend ostream & operator<<(ostream & os, const Z & z);
Definicja:
ostream & operator<<(ostream & os, const Z & z)
{
os << z.Re << „+” << z.Im <<„I”;
return os;
}
A teraz lepiej?
Z z1(2,3);
Z z2(3,4);
cout << z1 << z2;
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
13/21
Programowanie obiektowe
Języki i paradygmaty programowania
Przeciążenie operatora unarnego
Operator unarny, to operator, który wymaga tylko jednego argumentu (np. operator negacji).
Poniżej przedstawiono przykład przeciążenia operatora -, który zwraca negację liczby
zespolonej.
Deklaracja:
Z operator-() const;
Definicja:
Z Z::operator-() const
{
return Z(-Re, -Im);
}
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
14/21
Programowanie obiektowe
Języki i paradygmaty programowania
Konwersja i rzutowanie typów (C++)
Przykłady automatycznej konwersji między typami standardowymi:
double x = 2; liczba 2 (int) konwertowana na typ double
long y = 1; liczba 1 (int) konwertowana na typ long
int z = 2.98; liczba 2.98 (double) konwertowana na typ int
int p = ‘ ‘; znak ‘ ‘ (char) konwertowany na typ int
int * q = 100; błąd konwersji
int * q = (int *) 100; rzutowanie liczby 10 do wskaźnika do typu int.
W C++ można tak zdefiniowad klasę spokrewnioną z typem podstawowym lub z inną klasą
aby możliwe było wykonywanie konwersji między nimi. Przy czym należy określid czy
konwersja ma byd automatyczna, czy poprzez rzutowanie typów.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
15/21
Programowanie obiektowe
Języki i paradygmaty programowania
Konstruktor jako funkcja konwersji
Konstruktory, które posiadają jeden argument mogą pełnid rolę funkcji konwersji, czyli
mechanizmu, który przekształca wartośd argumentu na typ klasy. Zobacz przykład:
class Z
{
private:
double Re;
double Im;
public:
Z(double _Re) {Re=_Re; Im = 0;}
};
int main()
{
Z x = 10; //użycie konstruktora Z(double) do niejawnej konwersji liczby 10 na typ Z
return 0;
}
Konstruktory, które posiadają więcej niż jeden argument nie mogą pełnid roli funkcji konwersji.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
16/21
Programowanie obiektowe
Języki i paradygmaty programowania
explicit
Konstruktory, których definicje poprzedzone są słowem explicit, nie można wykorzystad
do niejawnej konwersji typów. Jednakże nadal możliwa jest jawna konwersja za pomocą
rzutowania
class Z
{
private:
double Re;
double Im;
public:
explicit Z(double _Re) {Re=_Re; Im = 0;} //automatyczna konwersja nie jest możliwa
};
int main()
{
Z x = 10; //błąd
Z y = Z(10); //działa, jawna konwersja
return 0;
}
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
17/21
Programowanie obiektowe
Języki i paradygmaty programowania
Funkcje konwersji
Funkcje konwersji to niestandardowe rzutowania typów, których można używad tak samo jak
zwykłych operacji rzutowania. Np.:
Z z(-1.2,0);
double x = double(z); jawna konwersja
double x = z; niejawna konwersja
Aby możliwe było wykonanie powyższych konwersji należy utworzyd funkcję konwersji o
następującej deklaracji:
operator nazwaTypu();
nazwaTypu oznacza typ do jakiego ma zostad przekształcony obiekt.
Warunki jakie musi spełniad funkcja konwersji:
• funkcja konwersji jest metodą klasy
• funkcja konwersji nie zwraca żadnego typu
• funkcja konwersji nie posiada argumentów
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
18/21
Programowanie obiektowe
Języki i paradygmaty programowania
Przykład funkcji konwersji
class Z
{
private:
double Re;
double Im;
public:
Z(double _Re) {Re=_Re; Im = 0;}
Z(double _Re, double _Im) {Re=_Re; Im = _Im;}
operator double() {return Re;}
};
int main()
{
Z x(10);
double a = x; // niejawna konwersja
Z y(-1,2);
double b = double(y); //jawna konwersja
return 0;
}
Gdy w klasie zdefiniowane są dwie lub więcej funkcji konwersji, wówczas w celu uniknięcia
niejednoznaczności używamy rzutowania.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
19/21
Programowanie obiektowe
Języki i paradygmaty programowania
Problem z konwersją
class Z
{
private:
double Re, Im;
public:
Z(double _Re) {Re=_Re; Im = 0;}
Z(double _Re, double _Im) {Re=_Re; Im = _Im;}
friend Z operator+(const Z & z, const Z & w)
{
return Z(z.Re + w.Re, z.Im + w.Im);
}
operator double() {return Re;}
};
int main()
{
Z a, b;
a = Z(1,2) + Z(-1,-2);
b = Z(1,2) + 2;
return 0;
}
Problem z niejednoznacznością w instrukcji Z(1,2) + 2. Z jednej strony liczba 2 zostaje
skonwertowana na typ Z i zostaje wywołana funkcja operator+(double, double), z
drugiej natomiast następuje konwersja Z(1,2) na 1 (double), czyli występuje double + int.
dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ
20/21
Programowanie obiektowe
Języki i paradygmaty programowania
KONIEC
Dziękuję za uwagę 
dr Dariusz Wardowski, Katedra Analizy Nieliniowej
21/21