Datové typy
Primitivní a objektové datové typy. Statické a dynamické typy. Substituční princip.
Primitivní a objektové datové typy
Primitivní datový typ
Jedná se o datový typ, který je atomický. Tedy slouží jako základní stavební jednotka. Tento typ nelze nijak dále dělit. Zabírá fixní místo v paměti, a to v závislosti na konkrétním typu. Primitivní datové typy se nachází v alokované v oblasti, které říkáme zásobník (stack).
Rozlišujeme několik základních datových typů, podle toho, jakou mohou obsahovat hodnotu a podle toho, jak velká tato hodnota může být (kolik místa zabírají v paměti)
- int
- jedná se celočíselný datový typ; v paměti zabírá
32
bitů; může tedy obsahovat číselnou hodnotu, která se vejde do32
bitů
- jedná se celočíselný datový typ; v paměti zabírá
- float
- jde o typ s pohyblivou plovoucí čárkou; používá se pro desetinná čísla s přesností
24
bitů; zbytek (8
bitů) je pro exponent
- jde o typ s pohyblivou plovoucí čárkou; používá se pro desetinná čísla s přesností
- double
- pokud potřebujeme větší přesnost než float, použijeme double
- boolean
- vyjadřuje buď hodnotu
true
, nebofalse
; v paměti zabírá minimálně velikost registru (minimálně 8 bitů)
- vyjadřuje buď hodnotu
- long
- také se mu říká long int; v paměti zabírá
64
bitů
- také se mu říká long int; v paměti zabírá
- char
- jedná se o typ, který pojme jeden znak; velikost je
8
bitů -> převod hodnoty na znak pomocí UTF-8 nebo ASCII tabulky
- jedná se o typ, který pojme jeden znak; velikost je
- enum
- velikost 32 bitů defaultně
- neboli výčet identifikátorů a jim přiřazených hodnot; jeho velikost je dána největší velikostí datového typu, který enum obsahuje; pokud máme v enumu int a float, tak enum bude velikosti floatu ->
64
bitů - v kódu se enum chová jako konstanta
- v jazyce java např. je prvnímu identifikátoru přiřazena hodnota 0 a záleží na pořadí ve výčtu identifikátorů
- pointer
- neboli ukazatel, drží v sobě odkaz do paměti -> adresu; jeho velikost je dána velikostí adresního registru;
Objektový datový typ
Je definovaný uživatelem. Objekt je struktura, která obsahuje proměnné a metody. Potřebuje tolik místa, kolik potřebují proměnné a metody obsažené v objektu.
Zatímco primitivní datové typy nemají žádné metody -> nic neumí, tak objekty umožňují provádět operace voláním metod na instanci objektu -> String
má například metodu size()
, která vrací jeho délku.
Objektové datové typy podporují dědičnost, všechny objekty dědí ze základní třídy Object
.
Objektové datové typy jsou alokované v oblasti paměti, které říkáme halda (heap). Ale reference na tento objekt (pointer), je uložena na zásobníku.
Alokace probíhá pomocí klíčového slova new
.
Halda vs Zásobník
Pro drtivou většinu jazyků platí, že pokud je proměnná inicializována pomocí new
(objekt či jiná dynamicky alokovaná proměnná), tak se alokuje na heapu. Tedy data, která objekt obsahuje, tak jsou alokovaná na heapu. Samotná proměnná si drží adresu, která ukazuje kde tyto data najdeme a je uložena v zásobníku (pointer).
Jsou zde malé rozdíly v jazycích, uvedeme si jako příklad Javu a C++.
V obou případech máme třídu A
class A{
int var;
}
Pokud chceme vytvořit objekt třídy A
, tak v Javě platí to, co je uvedené výše.
A object = new A(); // Na heapu se alokuje 32 bitů a na zásobníku prostor pro adresu, která ukazuje, kde se těchto 32 bitů nachází na heapu
V C++ máme na výběr, kde chceme alokovat
A a; // Jedná se o klasickou proměnnou, int var je alokována na zásobníku
A* a = new A(); // Jedná se o referenci, proměnná a je na zásobníku a proměnná var je na heapu -> stejné jako v Javě, akorát bez hvězdičky
U C++ ale platí, že s velkou mocí přichází velká zodpovědnost. Zatímco zásobník si uvolňuje paměť sám, tak halda (heap) vyžaduje, aby ji programátor v C++ uvolnit sám ručně. Jakmile přestane existovat reference v zásobníku na paměť inicializovanou na heapu, tak data již nejsou dostupná, ale stále zabírají místo v paměti. (Java toto nemá, používá tzv. Garbage Collector, který uvolňuje paměť, jakmile referenční proměnné opustí scope). Proto v jazyce C++ používáme např. destruktory, abychom tuto paměť zcela uvolnili.
Pěkné video na heap, stack, uložení jednotlivých proměnných, pointery či dynamickou alokaci paměti si můžete pustit zde
Statické a dynamické typy
Statický typ je takový typ proměnné, který dostal přiřazené místo při deklaraci. Velikost tohoto místa nelze změnit za běhu programu. Velikost je známa a dána při kompilaci. Jedinou možností je explicitní přetypování proměnných - tím změníme velikost paměti dedikovanou pro danou proměnou.
float a = 15;
int b;
Už při kompilaci je v paměti vytvořeno místo, pro obě proměnné tohoto typu, nezávisle na tom, zdali jsou inicializované. Primitivní datové typy jsou statické.
Dynamický typ je takový typ proměnné, které může být alokováno místo za běhu programu - runtime alokace.
A object;
///// O nějakou dobu později (program celou dobu běží.....)
object = new A();
Nebylo známo, kolik místa bude proměnná tohoto typu potřebovat při kompilaci. Toto místo ji bylo přiřazeno až při běhu programu.
Objektové datové typy jsou dynamické. Opětovným voláním object = new A()
později můžeme vytvořit nové místo pro tu samou proměnnou. (Reference zůstává v zásobníku, pouze se změní adresní prostor na heapu, na který odkazuje).
Substituční princip
Jedná se o princip OOP který říká, že objekt (zde instance třídy rodiče), může být nahrazen pod-objektem (instancí třídy potomka) aniž by to rozbilo program.
Potomek může nahradit předka, ale předek nemůže nahradit potomka.
- Potomek má alokovanou paměť stejného typu + má něco navíc.
- Nemůžme program rozbít ve smyslu přístupu do paměti (samozřejmě, že můžeme v potomkovi přepsat metody předka tak, aby program již nefungoval, ale z hlediska přístupu do paměti může potomek vždy nahradit předka)
Zdroje
-
Úvod do programování v C++. Jan Fesl [online] @2020 [citováno 18.05.2023]
Dostupné z: https://elearning.jcu.cz/pluginfile.php/47098/mod_resource/content/2/1.pdf -
Difference between Stack and Heap Allocation in java, c++, c?. Quora [online] @2014 [citováno 18.05.2023]
Dostupné z: https://www.quora.com/Difference-between-Stack-and-Heap-Allocation-in-java-c++-c -
What is the difference between a static and dynamic variable in C language?. Quora [online] @2019 [citováno 18.05.2023]
Dostupné z: https://www.quora.com/What-is-the-difference-between-a-static-and-dynamic-variable-in-C-language -
Liskov substitution principle. Wikipedia : The Free Encyclopedia [online] @2023 [citováno 18.05.2023]
Dostupné z: https://en.wikipedia.org/wiki/Liskov_substitution_principle