# OOP poznámky ke zkoušce

- tohle tak fuguje protože deklarace y na řádku 23 platí od toho místa dolů, to znamená že na řádku 21 se používá stará deklarce

- při dědění se nejprve vyhodnocnocuje konstruktor rodičovské třídy, pak až toho zděděného. Desktruktory se vyhodnocují přesně naopak (první zděděné, pak nadřazené)
- nezapoměň u příkladu v C že se předává hodnotou!
- striktní jmenná typová ekvivalence - musí mít přesně stejné typ (stejné jméno typu)
- volná jmenná typová ekvivalence - ekvivalentní jsou i aliasy na stejné jméno
- všechny typy v C jsou mutable, pokud neuvedeme const
- deklarace v pythonu platí pro celý blok:
```python=
c = 42
def foo():
print(c) # works
def bar():
print(c) # fails, variable usage before definition
c = 121
foo()
bar()
```
- C# = nekteré typy jsou value types, ostatní reference, pass by value
- Python = reference types, pass by sharing
- 
- velikost unionu je rovna velikosti největší položky
- 
- pole = prvky za sebou v paměti, většinou homogenní (stejný typ)
- list (seznam) = rekurzivní struktůra ($1 : (2 : [])$), nebo linked list
- head = první prvek
- tail = list bez prvního prvku
- improper list = rekurze nekončí připojením do prázdného listu ($(1 : 2)$)
- v C# klíčovým slovem "var" řekneme překladači, že má odvodit typ
- věci uložené na heapu nemají jméno, nedá se přistupovat jinak než nepřímo (ukazateli)
- ukazetelová aritmetika = $ptr + index \to$ k ptr se přičte $index∗sizeof(*ptr)$
- přiřazovací příkaz $=$ vrací hodnu (dá se použít ve výrazech)
- k typové konverzi dochází jen pokud dojde ke skutečné změně typu
```c=
// C
int i = 5;
int j = (int) i; // není explicitní typová konverze
```
```c=
// C
int i = 5;
long j = (short) i; // explicitní i implicitní konverze
```
```python=
i = 5
f = 1.5
a = i + i # bez konverze
b = f + f # bez konverze
c = i + f # implicitní konverze
f = 2 # bez konverze (reassignment)
```
- Referential transparency = libovolný výraz můžeme nahradit jeho hodnotou bez vlivu na chování programu
- Podprogram má pouze jeden vstupní bod

- C# a python $\to$ mají default parametry, při volání se dají použít poziční i pojmenované parametry (poziční musí být první, po vynechnání parametru nebo použítí pojmenovovaného parametru už nesmíme použít poziční)
- C# `params` keyword $\to$ pro proměnlivý počet argumentů stejného typu
- Obdržálkovi asociační brikule
- asociace zleva-doprava
- asociace zprava-doleva
- asociace zleva = zleva-doprava
- asociace doprava = zprava-doleva (xDDD)
- typy parametrů
- in $\to$ předané vstupní parametry (hodnotové parametry)
- out $\to$ výstupní parametry (return value, pass-by-value-result)
- in-out $\to$ vstupní parametry které jsou funkcí upraveny (například při pass-by-reference)
- předávání parametrů:
- pass-by-value (předávání hodnotou, in) $\to$ hodnota se zkopíruje do parametru
- pass-by-reference (předávání odkazem, in-out) $\to$ je předán odkaz na proměnnou, můžeme modifikovat objekt se kterým má proměnná vazbu, nebo do proměnné přidělit jinou hodnotu
- pass-by-sharing (předání sdílením, in-out) $\to$ předává se odkaz na objekt, ne odkaz na proměnou. Objekt můžeme modifikovat, nelze ale přiřadit jiný objekt do původní proměnné. Python předává sdílením.
- pass-by-result (předání výsledkem, out) $\to$ parametr podprogramu nepředává hodnotu, hodnoty uložené do parametru se **po skončení běhu podprogramu** propragují do původní proměnné
- pass-by-value-result (předání hodnotou-výsledkem, in-out) $\to$ jako pass-by-result ale parametr podprogramu předává i hodnotu pomocí pass-by-value
- pass-by-name (předání jménem, in-out) $\to$ textové nahrazení (jako makra v C). Výrazy použity jako parametry volání se nevyhodnocují, ale nahradí se jako text do podprogramu, až při běhu podprogramu dochází k jejich vyhodnocení
```c=
// C-like
int[] C = { 1, 2, 3 };
int i = 0;
void foo(int x)
{
i = 2;
x = 5; // x = 5 -> C[i] = 5 -> C[2] = 5 -> C = { 1, 2, 5 }
}
foo(C[i]);
```
- C# předávání parametrů
- value types (int, bool, enum, struct...) $\to$ pass-by-value
- reference types (class, string) $\to$ pass-by-sharing
- modifikátory in (refrence), ref (reference), out (result)
- C# `in` keyword $\to$ zamezí přiřazení do parametru, modifikace povolena (v C# 6.0 není)
- C# `out` keyword $\to$ pass-by-value-result
- C# `ref` keyword $\to$ pass-by-reference
- C# keywords pro paremetry je nutné uvést i při volání funkce (`foo(out x)`)
- C `const` zamezí modifikace a přirazení (jde obejít pomocí ukazatelů)
- přetížené podprogramy (overloading) $\to$ existuje více podprogramů se stejným jménem, ten správný je vybrán pomocí protokolu (C#)
- protokol = profil parametrů (počet, pořadí a typ parametrů) + návratový typ podprogramu
- overriding $\to$ přepsání existujícího podprogramu (Python)
- typy polymorfismu
- ad-hoc $\to$ overloading podprogramů, proměnlivý počet parametrů
- parametrický $\to$ generické parametry
- podtypový $\to$ dědičnost metod
- Generické funkce
- C++ $\to$ při překladu se vytvoří separátní kód pro každý použitý typ
- Java $\to$ generické parametry musí být třídy (možnost omezit množinu tříd), takže vytváří jen jednu kopii
- C# $\to$ umí pracovat i s primitivními typy, pro ty vygeneruje kód zvlášť
- Koprogramy (coroutines)
- více vstupních bodů
- kontrola nad tím kde se pokračuje ve výpočtu
- ADT (abstraktní datový typ)
- matematický model datového typu, který je definován svými hodnotami a operacemi nad ním
- ADT (user definied)
- skrýtá reprezentace
- rozhrání v jedné programové jednotce a není závislé na implementaci
- uživatele mohou vytvářet hodnoty tohoto typu
- OOP bylo zavedeno kvůli dědičnosti, ať lidé nemusí modifikovat ADT

- skrývání informací (information hidign) $\to$ informace které uživatel nepotřebuje jsou skryty (vnitřní reprezentace). Uživatele nemohou změnami poškodit struktůru a nemusí se učit vnitřní reprezentaci. Při změně kodu rozhrání zůstavá stejné
- zapouzdění (encapsulation) $\to$ pod stejným jménem spojuje data a operace na nich. **Často zahrnuje information hiding**
- v Python:
- encapsulation $\to$ class
- information hiding $\to$ není, ale:
- _bar $\to$ neměly by se používat, ale pořád jsou přístupné
- __bar $\to$ skoro private, při překladu jsou mangled (před jméno atributu se přidá _nazevtridy), s mangled jménem se ale pořád dají accesovat
```python=
class Test:
def __init__(self):
self.count = 0
def increment(self):
self.count += 1
test_object = Test()
test_object.increment() # Both are identical in functionality
Test.increment(test_object) # . before methods used the left operand as a call parameter for the method
```

- v C#:
- encapsulation $\to$ class, struct
- information hiding $\to$ private
- když v C# chceme zviditelnit atribut:
- `public` keyword $\to$ porušujeme information hiding
- gettery/settery $\to$ metody pro přístup k private atributům
- properties $\to$ jako atributy, ale můžeme jim nastavit způsob přístupu
- generuje skryté atributy
- properties samotné jsou vždy public
- `public string Name { get; set; }` $\to$ přístupný veřejně jako object.Name
- `public string Name { private get; private set; }` $\to$ přístupný jen ve třídě pro kterou je deklarován
- `public string Name { get; }` $\to$ set jenom v konstruktoru
- možnost uvést vlastní get/set funkce (musíme vytvořit vlastní skrytý atribut)
- ```c#=
public string Name {
get {
return _name;
}
set {
_name = value;
}
}
```
- třídy můžou být Generic
```c#=
class Stack<T> {
private List<T> items = new List<T>();
}
```
- Konstruktory
- nemají návratový typ
- název se musí shodovat s názvem třídy
- když neexistuje konstruktor, vytvoří se default konstruktor který hodnoty inicializuje na default value danou typem
- Destruktory (finalizers)
- Volají se na konci života objektu (Garbage collection, ne nutně hned po ztrátě odkazu na objekt), nelze je volat explicitně
- Pokud chceme uvolňovat drahé prostředky, tak radši implementovat metodu `Dispose()` z interfacu `IDisposable`
- `static` atributy a metody $\to$ nepatří instanci ale třídě samotné, existuje jen jedna kopie
- statické třídy
- mají jen statické členy
- nelze je inicializovat
- nemají konstruktor
- class based OOP = C#, python
- prototype based OOP = js, Lisp
- C# dědičnosti $\to$ jsou zděděny všechny atributy i metody, přístupnost zaleží na modifikátoru
- `public` $\to$ přístupný kdekoliv
- `private` $\to$ přístupný jen ve třívě, ve které je deklarován (přesto je ale zděděn)
- `proteccted` $\to$ přístupný jak ve třídě deklarace, tak i v třídách které jsou potomky třídy
- C# potomci před spuštěním svého konstruktoru volají rodičovský konstruktor, implicitně se volá konstruktor bez parametrů
- C# má dva druhy vazeb pro objekty
- statická (časná) vazba
- zděděné typy metody **skrývají**, dá se volat pomocí base
- deklarace původní metody zůstane nezměněná, metodě která tuto metodu skrývá se musí přidat klíčové slovo `new`
- dynamická (pozdní) vazba
- překrývání metod (metod overriding)
- původní třída musí mít klíčové slovo `virtual`, překrývající metoda `override`
```c#=
Device d = new SoundDevice();
d.PrintStatus();
// statická = při překladu dojde k vazbě proměnné d na typ Device, zavolá se metoda z Device
// dynamická = za běhu se zjistí typ proměnné d, výsledkem je typ SoundDevice, odkud se zavolá metoda
```

- Abstraktní třídy
- klíčové slova `abstract`
- nelze instancovat
- mohou obsahovat i neabstraktní metody
- Abstraktní metody
- nemají implementaci (pouze deklarace)
- implicitně jsou virtual, je nutno překrýt v potomcích
- Vícenásobná dědičnost
- v C# nejde, nutno řešit pomocí interface
- v Pythonu je, kolize metod je řešena pořadím deklarací tříd
- C# Interface
- podobné abstraktním třídám
- všechny metody a atributy mají jen deklaraci a jsou public by default
- nelze deklarovat static, abstract, virtual
- třídy interfacy implementují, nedědí, nepoužívá se keyword `override`
- Je možno tvořit hierarchii interfaců (navzájem se rozšiřují)
- Když se dědí metoda se stejným názvem z více interfaců, tak musíme pro každý interface implementovat metodu zvlášť
- Interface je typ, můžeme vytvářet hodnoty typu Interface
- možnost implementovat z více interfaců, případně implementovat vícekrát jeden interface pro různé typy při používání generik
```c#=
class Test : ITest<Bool>, ITest<Int> {}
```
- C# třída Object (System.Object)
- všechny objekty z ní dědí implicitně
- implementuje metody pro práci s objekty (CompareTo(), Equals()..), ty jsou virtuální a je možné je překrýt
-
- C# porovnání typů
- `test is Test` $\to$ vrací True pokud je typu `Test` nebo rodičovského typu
- `test.GetType() == typeof(Test)` $\to$ přesná ekvivalence
- C# přetypování objektů
- typecast `(Test) test` $\to$ vyhodí Exception když nelze převést
- `(test as Test)` $\to$ vrací `null` když nelze převést

- C# všechny value types dědí ze třídy `System.ValueType`
- C# boxing
- převod proměnné na typ `object`, proměnná se alokuje na haldě
- používá se pro metody, které berou parametry obecného typu Object (např `String.Concat("Answer", 42)`)
- Mixins
- rozšiřují funkcionalitu tříd
- sdíleno mezi třídami nehierarchicky
- porušuje principy OOP
- V Pythonu lze jako mixin přidat metody jako `__init__`, a comparison metody (`_le_`, `__ge__`, `__eq__`...)
- C# Mixins
- interface s implementací
- **nedědí se**, při použití nutno přetypovat `this` na typ mixinu
```c#=
((Test)this).TestMethod()
```
- C# exceptions
- všechny musí dědit z třídy System.Exception
- try, catch, finally
- chytají se specific exception, zachytí se když je testovaná třída exception nad třidou té vyhozené
- finally se spustí i když je v `try` return, break, nebo continue
- ve finally nesmí být return, break ani continue
- `throw new Exception("Message", e)`
- throw $\to$ rethrowne poslední zachycenou expception
- vyjímka se propaguje nahoru až do metody `Main`, pokud tam není zachycena, pak padá program
- podmínka u zachycení expcetion 
- Java exceptions
- můžeme používat return, break a continue v bloku `finally`
- všechny expcetion musí dědit z `Throwable`
- 2 podtřídy
- Error $\to$ JVM chyby
- Exception $\to$ mimo jiné uživatelsky definované expceptions, RuntimeException zodpovídají za většinu runtime expcetions
- Kontrolované vs nekontrolované vyjímky
- Nekontrolované $\to$ Error a RuntimeException
- Kontrolované
- ostatní `Throwable`
- musí být zachyceny přímo v metodě kde nastala, nebo v hlavičce metoda musí uvést, že zde může nastat chyba daného typu
```java=
void method() throws Expception {}
```
- Python expceptions
- try, except, finally, else
- možnost zachytávat více typů vyjímek v jednom catch bloku
- místo `throw` klíčové slovo `raise`
- else blok se spustí pokud v try bloku nedošlo k vyjímce



