Zaawansowane programowanie w C++ (PCP)
Wykład 2 - agregacja i dziedziczenie, polimorfizm.
dr in˙z. Robert Nowak
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
- p. 2/27
Powtórzenie
strona przedmiotu:
http://info.wsisiz.edu.pl/˜rno Powtórzenie:
programowanie strukturalne w C++
przestrzenie nazw
obiekty automatyczne, statyczne, dynamiczne i tymczasowe
klasy autonomiczne, konstruktor, destruktor, konstruktor
kopiuj ˛ acy
» Powtórzenie
Klasy autonomiczne
» Składowe statyczne klas
» Funkcje zaprzyja´znione
» Funkcje zaprzyja´znione (2)
» Operatory - powtórzenie
» Operatory - powtórzenie (2)
» Przeci ˛a˙zanie operatorów
» Operator =
» Metody stałe
» Klasa std::string
» Klasa std::vector
Agregacja i dziedziczenie
Składowe statyczne klas
Składowa statyczna:
zmienna globalna (jedna kopia w programie),
nie musi by´c publicznie dost ˛epna (mo˙ze by´c prywatna),
obowi ˛ azkowo musi by´c zdefiniowana (i zainicjowana).
class Foo {
static int fooId;//składowa statyczna public:
static int getNewId() { return ++fooId; } //metoda statyczna ...
};
int Foo::fooId = 0; //Definicja i inicjacja składowej statycznej
int newId = Foo::getNewId(); //Wołanie metody statycznej Foo f; f.getNewId(); //Wołanie metody statycznej
Stosuj stałe statyczne! static const int SIZE = 40;
» Powtórzenie
Klasy autonomiczne
» Składowe statyczne klas
» Funkcje zaprzyja´znione
» Funkcje zaprzyja´znione (2)
» Operatory - powtórzenie
» Operatory - powtórzenie (2)
» Przeci ˛a˙zanie operatorów
» Operator =
» Metody stałe
» Klasa std::string
» Klasa std::vector
Agregacja i dziedziczenie
- p. 4/27
Funkcje zaprzyja´znione
Dost ˛ep do prywatnych składowych dla funkcji, które nie s ˛ a metodami.
class Foo { ...
friend int get(const Foo& f);
...
private:
int i;
};
int get(const Foo& f) { return f.i;
}
funkcje zaprzyja´znione s ˛ a cz˛e´sci ˛ a interfejsu klasy.
» Powtórzenie
Klasy autonomiczne
» Składowe statyczne klas
» Funkcje zaprzyja´znione
» Funkcje zaprzyja´znione (2)
» Operatory - powtórzenie
» Operatory - powtórzenie (2)
» Przeci ˛a˙zanie operatorów
» Operator =
» Metody stałe
» Klasa std::string
» Klasa std::vector
Agregacja i dziedziczenie
Funkcje zaprzyja´znione (2)
mo˙zna „zaprzyja´zni´c” metod ˛e klasy (a nawet wszystkie metody innej klasy),
deklaracja friend mo˙ze wyst ˛ api´c w dowolnej sekcji,
nie tylko metody mog ˛ a modyfikowa´c prywatne dane -
„złamanie” obiektowego podej´scia.
Podział kodu:
metoda
ma dost ˛ep do składowych prywatnych,
jest w zasi ˛egu klasy,
jest wołana dla obiektu (ma wska´znik this )
metoda statyczna ma dost ˛ep do składowych prywatnych
jest w zasi ˛egu klasy
funkcja zaprzyja´zniona ma dost ˛ep do składowych prywatnych
» Powtórzenie
Klasy autonomiczne
» Składowe statyczne klas
» Funkcje zaprzyja´znione
» Funkcje zaprzyja´znione (2)
» Operatory - powtórzenie
» Operatory - powtórzenie (2)
» Przeci ˛a˙zanie operatorów
» Operator =
» Metody stałe
» Klasa std::string
» Klasa std::vector
Agregacja i dziedziczenie
- p. 6/27
Operatory - powtórzenie
priorytet,
ł ˛ aczno´s´c.
Oznaczenie Opis
:: operator zasi ˛egu
. -> dost ˛ep do składowej
[] indeksowanie
() operator funkcyjny
++ -- inkr. dekr. pre- i postfiksowa
˜ ! negacja bitowa, negacja logiczna
- + jednoargumentowy + i -
& * adres argumentu, wyłuskanie
new new[] delete
delete[]
tworzenie i zwalnianie
.* ->* dost ˛ep do składowej (przez wska´znik)
» Powtórzenie
Klasy autonomiczne
» Składowe statyczne klas
» Funkcje zaprzyja´znione
» Funkcje zaprzyja´znione (2)
» Operatory - powtórzenie
» Operatory - powtórzenie (2)
» Przeci ˛a˙zanie operatorów
» Operator =
» Metody stałe
» Klasa std::string
» Klasa std::vector
Agregacja i dziedziczenie
Operatory - powtórzenie (2)
* / % mno˙zenie, dzielenie, modulo
+ - dodawanie, odejmowanie
<< >> przesuwanie bitowe
< <= > >= porównywanie
== != badanie równo´sci, ró˙zno´sci
& iloczyn bitowy
ˆ ró˙znica symetryczna (bitowa)
| suma bitowa
&& iloczyn logiczny
|| suma logiczna
? : wyra˙zenie warunkowe
= *= /= %= += -= <<=
>>= &= |= ˆ=
operatory przypisania
, operator przecinka
» Powtórzenie
Klasy autonomiczne
» Składowe statyczne klas
» Funkcje zaprzyja´znione
» Funkcje zaprzyja´znione (2)
» Operatory - powtórzenie
» Operatory - powtórzenie (2)
» Przeci ˛a˙zanie operatorów
» Operator =
» Metody stałe
» Klasa std::string
» Klasa std::vector
Agregacja i dziedziczenie
- p. 8/27
Przeci ˛ a˙zanie operatorów
Nast ˛epuj ˛ ace wołania s ˛ a identyczne dla kompilatora (przykład dla operatora dwuargumentowego)
aa ⊕ bb
aa.operator ⊕ (bb) //Metoda
operator ⊕ (aa,bb) //Funkcja
aa + bb
aa.operator+(bb) //Metoda operator+(aa,bb) //Funkcja
Mo˙zliwo´s´c definiowania operatorów:
dostarczaj ˛ a wygodn ˛ a notacj ˛e dla nowych typów;
nie mo˙zna zdefiniowa´c nowych symboli operatora (np. ** );
nie mo˙zna u˙zy´c innej liczby argumentów.
nie mo˙zna zdefiniowa´c: :: . .*
tylko wyra˙zenia zawieraj ˛ ace typy zdefiniowane przez
u˙zytkownika u˙zywaj ˛ a przeci ˛ a˙zonych operatorów.
» Powtórzenie
Klasy autonomiczne
» Składowe statyczne klas
» Funkcje zaprzyja´znione
» Funkcje zaprzyja´znione (2)
» Operatory - powtórzenie
» Operatory - powtórzenie (2)
» Przeci ˛a˙zanie operatorów
» Operator =
» Metody stałe
» Klasa std::string
» Klasa std::vector
Agregacja i dziedziczenie
Operator =
Bardzo wa˙zna metoda (tworzy kopi ˛e obiektu).
1. usuwa star ˛ a zawarto´s´c obiektu
2. tworzy now ˛ a zawarto´s´c (to samo robi konstruktor kopiuj ˛ acy)
f = f;//przypisanie obiektu samego do siebie a[i] = a[j];//mo˙ zliwe przypisanie j.w.
px = *py; //mo˙ zliwe przypisanie j.w.
Uwaga! Nale˙zy si ˛e zabezpieczy ´c przed przypisaniem a=a
class Foo { public:
Foo& operator=(const Foo& r) {
if(&r != this)//zabezp. przed samo-przypisaniem ...
return *this; //Zawsze powinien zwraca´ c *this }
};
» Powtórzenie
Klasy autonomiczne
» Składowe statyczne klas
» Funkcje zaprzyja´znione
» Funkcje zaprzyja´znione (2)
» Operatory - powtórzenie
» Operatory - powtórzenie (2)
» Przeci ˛a˙zanie operatorów
» Operator =
» Metody stałe
» Klasa std::string
» Klasa std::vector
Agregacja i dziedziczenie
- p. 10/27
Metody stałe
Metody które mo˙zna woła´c dla obiektu const
typedef int Element;//Typ elementu przechowywanego na li´ scie class Node {
public:
const Element& get() const;//Mozna wolac dla stalego obiektu Element& get();
private:
Element element_;
};
const Element& Node::get() const { /* Tutaj implementacja */
return element_;
}
//Implementacja u˙ zywa poprzedniej wersji Element& Node::get() {
return const_cast<Element&>(
static_cast<const Node&>(*this).get() );
}
» Powtórzenie
Klasy autonomiczne
» Składowe statyczne klas
» Funkcje zaprzyja´znione
» Funkcje zaprzyja´znione (2)
» Operatory - powtórzenie
» Operatory - powtórzenie (2)
» Przeci ˛a˙zanie operatorów
» Operator =
» Metody stałe
» Klasa std::string
» Klasa std::vector
Agregacja i dziedziczenie
Klasa std::string
nagłówek #include <string>
inicjacja:
string s1; //napis pusty
string s2(¨Ala¨) ;
string s3 = ¨Ala ma kota¨;
porównywanie napisów, operatory == , !=
if(s1 == s2) ...
if(s2 != string(¨ABCD¨) ) ...
uzyskanie napisu w stylu ’C’: metoda c_str()
const char* nap = s2.c_str();
konkatenacja (ł ˛ aczenie napisów) - operator +
string s = s2 + string(¨Ola¨) + s2;
badanie długo´sci, podnapisy, wyszukiwanie i wiele innych.
» Powtórzenie
Klasy autonomiczne
» Składowe statyczne klas
» Funkcje zaprzyja´znione
» Funkcje zaprzyja´znione (2)
» Operatory - powtórzenie
» Operatory - powtórzenie (2)
» Przeci ˛a˙zanie operatorów
» Operator =
» Metody stałe
» Klasa std::string
» Klasa std::vector
Agregacja i dziedziczenie
- p. 12/27
Klasa std::vector
Zast ˛epuje (w wi ˛ekszo´sci przypadków) tablic ˛e.
nagłówek #include <vector>
inicjacja
vector<int> v; //pusty wektor obiektów int
vector<double> v2(3);
vector<Punkt> v3[2]; //Uwaga!
Dostêp do elementu
double d = v2[1]; //bez kontroli zakresu
int i = v.at(5); //kontrola zakresu
Metoda push_back dodaje element na koniec, np.
v.push_back(4);
Metoda size() zwraca liczb ˛e elementów.
Metoda empty() bada, czy kontener nie jest pusty.
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
Tworzenie nowych klas
Wielokrotne wykorzystanie kodu:
Wykorzystanie istniej ˛ acych klas bez naruszania ich implementacji.
Mo˙zliwo´s´c szybkiej zmiany struktury programu.
Umo˙zliwia programowanie przyrostowe.
Budowa klas na podstawie ju˙z istniej ˛ acych:
agregacja,
dziedziczenie.
J ˛ezyk UML (Unified Modeling Language) - diagram klas.
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
- p. 14/27
Agregacja
Agregacja - relacja typu „składa si ˛e z” lub „posiada”.
Przedmiot Nauczyciel
- imie - nazwisko
- nazwa
+getName() +getName()
class Przedmiot {
//Definicja klasy };
class Nauczyciel { //Interfejs
private:
std::vector<Przedmiot*> przedmioty_;
//Pozostałe składowe
};
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
Kompozycja
Szczególny przypadek agregacji: obiekt składowy nie mo˙ze istnie´c bez obiektu głównego.
Silnik Samochód
- marka - model
- rodzaj
+getName() +getType()
class Silnik {
//Definicja klasy
};
class Samochod { //Interfejs private:
Silnik silnik_;
//Pozostałe składowe
};
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
- p. 16/27
Po co dziedziczenie?
Relacja „jest” lub „mo˙ze by´c traktowany jako”
class Pracownik {
//Interfejs klasy private:
string imie;
string nazwisko;
};
class Kierownik {
//Interfejs klasy
private:
Pracownik prac_;
vector<Pracownik*> podlegli_;
};
Wady: kompilator nie wie, ˙ze Kierownik to tak˙ze Pracownik
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
Dziedziczenie
Relacja „mo˙ze by´c traktowany jako”, lub „jest podtypem”.
Kierownik Pracownik
- imie - nazwisko
- department +getName()
+getDepartment()
klasa bazowa
klasa pochodna
class Pracownik {
//Definicja klasy };
class Kierownik : public Pracownik { //Definicja klasy
};
Bazowa
Pochodna
Dziedziczenie wprowadza powi ˛ azanie pomi ˛edzy typami.
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
- p. 18/27
Agregacja - interfejs
Agregacja - nale˙zy dostarczy´c nowy interfejs.
class Silnik { public:
void uruchom();
//Definicja klasy cd.
};
class Samochod { public:
void uruchomSilnik() { silnik.uruchom(); } //Interfejs cd.
private:
Silnik silnik_;
//Pozostałe składowe
};
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
Dziedziczenie - interfejs
Dziedziczenie - klasa potomna zachowuje interfejs.
class Pracownik { public:
std::string imie() const;
//Definicja klasy cd.
};
class Kierownik : public Pracownik { //Definicja klasy
};
Kierownik k;
k.imie();
Dziedziczenie publiczne (najcz˛e´sciej stosowane):
Metody publiczne klasy bazowej s ˛ a publiczne w klasie pochodnej;
Metody prywatne klasy bazowej s ˛ a prywatne w klasie
pochodnej;
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
- p. 20/27
Konwersje typów
Dziedziczenie: klasa pochodna zawiera obiekt klasy bazowej (wszystkie składowe i metody).
Mo˙zliwo´s´c rzutowania „w gór ˛e”:
Pracownik p;
Kierownik k;
Pracownik* p2 = &k; //OK, mo˙ zna kierownik te˙ z jest pracownikiem Kierownik* k2 = &p; //BŁ ˛ AD!! nie ka˙ zdy kierownik jest pracownikiem
istnieje mo˙zliwo´s´c rzutowania wska´znika(referencji) do klasy pochodnej na wska´znik (referencj ˛e) do klasy bazowej;
istnieje mo˙zliwo´s´c tworzenia obiektu klasy bazowej na podstawie klasy pochodnej;
Ale nie odwrotnie!
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
Konstrukcja i destrukcja
Konstrukcja obiektów zło˙zonych:
Konstruktor dla klasy bazowej (domy´slnie bezparametowy)
Konstruktory dla składowych (domy´slnie bezparametrowe)
Mo˙zna woła´c inne konstruktory - lista inicjatorów konstruktora:
dla klas bazowych: nazwa typu,
dla klas, które s ˛ a składowymi: nazwa składowej.
Konstruktory te s ˛ a wołane przed rozpocz˛eciem kodu konstruktora.
Destrukcja obiektów zło˙zonych:
Destruktor woła (po zako ´nczeniu działania) destruktory dla obiektów składowych oraz dla klas bazowych.
Prawie nigdy nie ma potrzeby wołania jawnie destruktorów.
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
- p. 22/27
Dziedziczenie czy agregacja?
dziedziczenie - relacja typu typ - podtyp;
pochodna posiada wszystkie składowe bazowej;
nie narusza si ˛e mechanizmów ochrony;
pochodna mo˙ze by´c u˙zywana tam, gdzie bazowa (rzutowanie wska´znika)
agregacja - gdy budowa z
mniejszych kawałków wi ˛ekszej cało´sci;
Kierownik Pracownik
- id
- nazwisko
- sekcja - pracownicy +getId()
+liczbaPodl()
agregacja: prostsza kontrola - nale˙zy j ˛ a faworyzowa ´c
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
Hierarchie klas
Trójkąt Prostokąt Koło Złożona Figura
class Figura {...};
class Kolo : public Figura {...};
class Zlozona : public Figura { private:
vector<Figura*> sklad_;
};
Klient Pracownik
Specjalista Osoba
Zarząd Administracja
class Osoba {...};
class Pracownik
: public Osoba {...};
class Specjalista
: public Pracownik {...};
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
- p. 24/27
Wycinanie
Działanie konstruktora kopiuj ˛ acego lub operatora przypisania:
class Pracownik { ... };
class Kierownik : public Pracownik { ... };
Kierownik k(...);
Pracownik p = k;
kopiuje tylko cz˛e´s´c klasy,
´zródło niespodzianek i bł ˛edów,
rozwi ˛ azanie: przekazywanie wska´zników lub referencji do
obiektów.
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
Składowe chronione
Sekcja protected - dost ˛ep do składowych lub metod dla:
metod klasy pochodnej;
funkcji zaprzyja´znionych z klas ˛ a pochodn ˛ a.
własne metody metody klasy pochodnej inny kod
private + - -
protected + + -
public + + +
class Foo { public:
//Interfejs protected:
//Składowe i metody dost˛ epne dla klas pochodnych
private:
//Implementacja
};
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie
- p. 26/27
Przedefiniowywanie metod
(redefining) w odró˙znieniu do nadpisywania (overriding, funkcje wirtualne)
class Pracownik { public:
void drukuj(ostream& os) const { os << ¨nazwisko:¨ << nazwisko_;
} };
class Kierownik : public Pracownik { public:
void drukuj(ostream& os) const { Pracownik::drukuj(os);
os << ¨ kierownik działu:¨ << dzial_;
} };
przedefiniowywanie: zmiana zachowania metody;
je˙zeli sygnatury s ˛ a ró˙zne - zmiana interfejsu, wskazuje na
bł ˛ ad projektowy.
» Powtórzenie
Klasy autonomiczne
Agregacja i dziedziczenie
» Tworzenie nowych klas
» Agregacja
» Kompozycja
» Po co dziedziczenie?
» Dziedziczenie
» Agregacja - interfejs
» Dziedziczenie - interfejs
» Konwersje typów
» Konstrukcja i destrukcja
» Dziedziczenie czy agregacja?
» Hierarchie klas
» Wycinanie
» Składowe chronione
» Przedefiniowywanie metod
» Zakrywanie