čtvrtek 12. dubna 2007

PDT a OOP

Každý, kdo chce efektivně pracovat s objekty, musí použít nástroj, který mu umožní automaticky doplňovat potřebné informace. Jinými slovy, použije nějaké IDE, které usnadní práci při psaní kódu.

Když si představím, že vytvořím objekt, který obsahuje několik metod, rád bych tyto metody rovnou volal. U jazyků, které dodržují striktně typovou kontrolu, je to jednoduché. Každý parametr metody musí mít typové označení, stejně tak návratová hodnota. U PHP je situace o dost horší. Jediné, co mi samotné PHP umožňuje je, že u parametru metody mohu definovat o jaký typ objektu se jedná. Navíc jsem omezen pouze na objekty a pole.
Jenže metody mi často vrací další objekty a tyto objekty někde dál používám. Samotný plugin od ZENDu (PHP Development Tool = PDT) na to jde od lesa. Dovolí mi používat komentáře, ve kterých si jasně definuji, o jaký typ se vlastně jedná. Lepší než další povídání bude ukázka.

class TridaA {
public function foo() {}
}
class TridaB {
private $tridaA;
public function __construct() {
$this->tridaA = new TridaA();
}
public function zavolejFoo() {
$this->tridaA->foo();
}
}


Z ukázky je jasné, že atribut třídy B je vlastně objekt z třídy A. Eclipse mi sice umožní automaticky zavolat metodu foo();, ale pouze v konstruktoru, protože dál už nevidí. V metodě zavolejFoo(); mám prostě smůlu. Mám ale možnost samotný atribut třídy okomentovat, čímž vyjádřím, že se jedná o objekt třídy A a pak již vše funguje, jak má.


/**
* @var TridaA
*/
private $tridaA;


Další věcí budiž parametry metody. Na začátku jsem psal, že PHP sice dovoluje definovat typ pro parametr metody, ale ne vždy tak činíme. Pokud typovou kontrolu na parametr metody definovat nechci, ale chci, aby Eclipse poznalo, že se jedná o tu či onu instanci objektu, jednoduše metodu okomentuji.


/**
* @param TridaA $tridaA
*/
public function setTridaA($tridaA) {
$tridaA->foo();
}


U definování samotného parametru metody je třeba mít na paměti, že musím také definovat, o jaký parametr se vlastně jedná.

Poslední věcí je návratová hodnota metod. K tomuto mohu opět použít komentář a říci tak Eclipse, o jaký návratový typ se vlastně jedná.


/**
* @return TridaA
*/
public function getTridaA() {
return new TridaA();
}


Pokud tedy pracujete s objekty a používáte k tomu jazyk, který má dynamické typování, jistě Vás často naštve, že nevíte, co vlastně v danou chvíli proměnná obsahuje. Toto Vám sice nezaručí, že nebudete chybovat při zjišťování typů, ale zaručí, že samotné programovací prostředí Vám řekne, co teď vlastně používáte.

Jestli jste neměli v oblibě komentáře, tak nyní si je určitě zamilujete :)

O psaní komentářů by se dala napsat celá kniha, ale o tom zase jindy.

středa 4. dubna 2007

JSF & Facelets

Samotné JavaServer Faces (JSF) je ve své podstatě jednoduchý framework na view vrstvu, který komunikuje pomocí Backing Beans. JSF v žádném případě neruší metodiky JSP-Servletů, pouze je potlačuje ve prospěch vývojářů a snaží se nabídnout alternativu pomocí JSF.

V JSF je několik vlastností (zejména uvnitř faces-config.xml), které jistě stojí za to prozkoumat:

  • Navigace

  • Lokalizace a vlastní definice messages

  • Definice managed-beans (request, session) ...

  • Psaní HTML komponent v pomocí jsf/html

  • Tvorba vlastních UI komponent



Pro vývojáře, kteří mají s podobnými typy frameworků již zkušenosti, jistě není problém se JSF doučit. Ve chvíli, kdy je pro Vás jsp-servlet nový pojem, doporučuji rovnou začít na JSF. Samotná metodika Vás nakonec stejně donutí se jsp-servlety částečně doučit.

Když to vezmu do důsledků, tak jako vývojář v PHP jsem měl k jakýmkoliv frameworkům odpor. Ne snad z toho důvodu, že bych si raději všechno psal sám, ale z toho důvodu, že jsem nikdy nevěřil, že ten či onen framework bude i nadále podporován a že mi poskytne komplexní řešení.
U JSF je situace jiná. Samotný framework (stejně jako např. JavaPersistence API), je standardem SUNu, což samo o sobě dává pocit jakési jistoty, že se samotné API neučím nadarmo. Mám jistou záruku, že bude více využíván, dále podporován, či na něm budou postaveny další implementace, které se budou snažit dodržet standard a k tomu použiji své vlastní rozšíření.
Takovouto podobnost mohu nalézt např. mezi JPA a Hibernate, kde Hibernate se stalo plně kompatibilní s JPA a navíc nabízí vlastní rozšíření (např. CriteriaAPI).

Abych jen neházel samou chválou, přece jen mně na JSF trochu vadila jedna věc a to je "šablonovací systém". Nebo chcete-li, možnost, kdy budu vkládat své stránky do stejné "formičky".

Nakonec jsem našel "Facelets", což je v podstatě rozšíření samotného JSF, které je ovšem zaměřeno právě na šablonovací systém. Samotný popis lze nalézt zde.
Pro NetBeans existuje i vlastní plugin, který je popsán zde.

Takže pokud někdo začíná s webovými aplikacemi v Jave, doporučuji JSF-EJB3-JPA. I když není Java EE 5 zrovna jednoduchá záležitost (alespoň pro mě), tak stojí za to alespoň nahlédnout, jak vlastně taková architektura vícevrstvé aplikace (z pohledu Javy), vypadá.

Na webu Jakuba Vrány o PHP, se někteří lidé domnívali, že URL v JSF je statická. Na malý problém existuje malá náplast a tou je "" v navigation-case. Stejnou fintu je třeba použít, pokud budu tvořit zabezpečenou aplikaci přes url-pattern (/secure/*) v security-constraint.

úterý 27. března 2007

OOP v PHP5 díl.6 - viditelnost a klíčová slova

Pokud budeme mluvit o objektech jako o zapouzdřených componentách, musíme nějakým způsobem zajistit, aby daná komponenta poskytovala jen to, co skutečně má. Pokud bychom ignorovali viditelnost jako takovou, vznikl by nám mezi jednotlivými třídami chaos, který by zapříčinil nepoužitelnost.

Vezmu to pěkne od začátku, mám atributy třídy a metody třídy. Obě tyto vlastnosti každého objektu mají volitelnou viditelnost, která je rozdělena do tří úrovní:

  • public

  • protected

  • private



Public
Jakákoli vlastnost objektu nastavená viditelností public mi umožňuje říci, že: "každý má právo k této vlastnosti přistupovat".

Protected
Narozdíl od public, má protected omezení jen na viditelnost v samotné třídě a třídách, které jsou potomkem.

Private
K vlastnostem označeným jako private může přistupovat pouze a jedině vlastní třída.

Když jsem v minulých dílech tvrdil, že atributy třídy by měly být označeny vždy jako private, neříkal jsem úplně pravdu. Při tvorbě vlastních tříd se dost často setkáme s problémem, kdy bych potřeboval použít daný atribut jako parametr metody. Jinými slovy řečeno, podle parametru mi metoda vykoná to či ono.

class HTML_Form_Input {
private $value;
.....
public function __construct($value) {
$this->value = $value;
}

public function setValue($value) {
$this->value = $value;
}

public function getValue() {
return $this->value;
}
.....
}


Tato jednoduchá třída implementovala private jako viditelnost pro atribut třídy a public jako atribut pro konstruktor a setry a getry. Teď ovšem nastává problem, kdy bych potřeboval identifikovat typ samotného inputu. Jedna z možností by byla, že bych metodě setType(String) vždy posílal vlastním stringem, o jaký typ se vlastně jedná. Toto sice lze, ale my se budeme snažit o co nejlepší znovupoužitelnost a možnost nastavení těchto typů přímo ve třídě, abychom nemuseli při refactoringu dohledávat všechny různé překlepy, atd.

class HTML_Form_Input {
const TYPE_HIDDEN = "hidden";
....
}
$input = new HTML_Form_Input("jmeno");
$input->setType(HTML_Input_Form::TYPE_HIDDEN);


Konstanta jako taková je neměná a je přístupná mimo vytvořený objekt. Pokud bych chtěl danou konstantu volat přímo ve třídě, využiji k tomu self::.

S dalším klíčovým slovem, se kterým se můžete setkat, je static. Statický atribut či metoda je taková vlastnost, která mi zapříčiní, že ji mohu získat aniž bych musel vytvářet objekt. Její hodnota je tedy nezávislá na tom, zda objekt existuje či nikoli. Pokud bych to převedl do praxe, můžu pomocí statického atributu třídy zjišťovat, kolikrát jsem vytvořil objekt z dané třídy.

Další ukázky si nechám do příštího dílu, který budu věnovat Design Patterns, neboli návrhovým vzorům. Ukážu např. implementování Iteratoru, který lze nativně v PHP 5 nalézt.

pondělí 19. března 2007

PHP & Java: SHA-1

Při vývoji javovské aplikace jsem narazil na problém autentifikace uživatelů. Problém spočíval v tom, že mám tabulku uživatelů, která obsahuje hash hesla, který je hashován pomocí PHP.

echo sha1(sha1("heslo"));


Čekal jsem, že v Java API naleznu podobnou metodu na hash Stringu, bohužel jsem hledal marně :)

Jelikož jsem si nevěděl rady, poprosil jsem na konferenci na java.cz o malou pomoc. Po odpovědi obsahující link, na tvorbu hashe ze Stringu, jsem moc moudrý nebyl :(
Potom jsem dostal ovšem odpověď v podobě třídy, kterou jsem nakonec po své úpravě byl schopen aplikovat.

package org.dostal.dochazka.crypt;

import java.security.MessageDigest;
/**
* Statické metody pro výpočet hash
*
* @author Ales Dostal;
*/
public class HashUtil {

public static final String HASH_TYPE = "SHA-1";

/**
* konstruktor
*/
private HashUtil() {}

/**
* vypocita SHA-1 hashovaci klic z byte[] a vrati jej jako HEXa retezec
*
* @param pass heslo ve String
* @return HEXa řetězec
*/
public static String SHA1AsString(String pass) {
return SHA1AsString(pass.getBytes());
}

/**
* vypocita SHA-1 hashovaci klic z byte[] a vrati jej jako HEXa retezec
*
* @param pass heslo v byte[]
* @return HEXa retezec
*/
public static String SHA1AsString(byte[] pass) {
return hex(SHA1(pass));
}

/**
* vypocita SHA-1 hashovaci klic z char[] a vrati jej jako HEXa retezec
*
* @param pass heslo v char[]
* @return HEXa retezec
*/
public static String SHA1AsString(char[] pass) {
return SHA1AsString(String.valueOf(pass));
}

/**
* Vypočte SHA-1 hashovací klíč z řetězce
*
* @param secret pomocný klíč
* @return pole bytů
*/
private static byte[] SHA1(byte[] pass) {
byte[] mac = new byte[20];
try {
MessageDigest sha = MessageDigest.getInstance(HASH_TYPE);
sha.update(pass);
mac = sha.digest();
} catch (Exception e) {
e.printStackTrace();
}
return mac;
}

/**
* Převede pole bytů na HEXa řetězec.
*
* @param data pole bytů
*/
private static String hex(byte[] data) {
StringBuilder sb = new StringBuilder();
for (byte b : data) {
sb.append(Character.forDigit((b & 240) >> 4, 16));
sb.append(Character.forDigit((b & 15), 16));
}
return sb.toString();
}

}


Nyní jsem schopen přistupovat k porovnání hashe jak z PHP, tak z Javy. Sice je to taková maličkost, ale občas dost důležitá :)

echo sha1("heslo");

System.out.println(HashUtil.SHA1AsString("heslo"));

úterý 6. března 2007

OOP v PHP 5 - teorie dědičnosti a ORM

Když se vrátím na začátek, kde jsem tvrdil, že objekty jsou jakýsi obal nad procedurálním kódem, tak se musím zamyslet nad tím, jak umožnit, abych nemusel stále dokola zabalovat jednu a tu samou věc. Třídy bych měl vždy navrhovat tak, aby obsahovali jen to nejnutnější a nebyly zbytečně vázany na jiné třídy. Navíc třídy by něměli obsahovat pevnou vazbu na třídy, které jsou navrženy v jiných úrovních.

Příklad:
Do třídy pro zobrazení stromové struktury nebudu cpát třídu, která mi vrací data stromu. Raději ve třídě stromu napíši metodu, která bude umět přijmout data a zobrazit je. Na získání dat vytvořím jinou třídu.
Když budu později potřebovat zobrazit strom s jinými daty, prostě použiji již hotovou třídu stromu, která přijímá data.


Tím dokážu vytvořit znovupoužitelný kód. K tomu, abych mohl takto tvořit třídy, ale musím znát všechny možnosti objektů. Nyní se vratím k další možnosti objektů a tou je dědičnost.

Dědičnost je vlastnost, která mi umožňuje rozšířit třídu a pozměnit její chování. Nic víc, nic míň.

Na začátku jsem napsal, že třídy by měli být co nejořezanější, neměli by obsahovat věci, které by ji svázali natolik, že by obsahovala zbytečné a nevyužitelné vazby. Pokud ovšem v projektu potřebuji danou třídu rozšířít a to tak, že dané rozšíření budu využívat vícekrát, prostě napíši si novou vlastní třídu, která bude dědit vlastnosti z minulé třídy.

Příklad:
Mám třídu na zobrazování filtrace nad daty. Teď je ovšem problém, že v některých případech filtruji přes ty samé položky (př. název). Jednou možností je, pořád do objektu posílat objekt (komponentu) název. Jelikož už vím, co je dědičnost, mohu ji využít. Vytvořím novou třídu, která bude dědit třídu filtrace a navíc bude automaticky vkládat komponentu pro název.


Toto je jedna z možností jak dědičnost využít, přiznávám, že ne moc efektivní, jistě existují i jiné možnosti, ale jako příklad je to postačující.

Asi lepším příkladem je struktura dat v databázi. Dnes jsou nejrozšířenejší relační typy databází. Jistě jsou velmi efektivní, rychlé a snadné na práci, ale pro nás jsou dost nevyhovující, proto existuje ORM (objektově relační mapování), což není nic jiného, než, že tabulku v databázi převedeme na objekt.

CREATE TABLE zamestnanec (
cislo int NOT NULL,
jmeno varchar(100) NOT NULL,
prijmeni varchar(100) NOT NULL,
PRIMARY KEY(cislo)
);



class Zamestnanec {
private $cislo;
private $jmeno;
private $prijmeni;
/* + setry a getry ke vsem atributum */
}


Nyní vytvoříme tabulku "uzivatele". U uživatelů budeme potřebovat navíc heslo, počet přihlášení, poslední přihlášení. V databázi tedy vytvoříme tabulku "uzivatele", která bude mít primární klíč osobní číslo, které bude zároveň cizím klíčem s vazbou do tabulky zaměstnanců na osobní číslo.

Potom pro výpis uživatelů použijeme něco takového:
SELECT u.*, z.jmeno, z.prijmeni
FROM uzivatele u
INNER JOIN zamestnanci z ON u.cislo = z.cislo


To je v pořádku, databázi máme, ale jak to uděláme v našem projektu, kde máme objekty? Velice jednoduše, použijeme dědičnost.

class Uzivatel extends Zamestnanec {
private $heslo;
private $pocetPrihlaseni;
private $posledniPrihlaseni;
/* setry a getry */
}


Nyní jsem vlastně rozšířil zamestnance o další atributy aniž bych musel znovu psát jeho vlastnosti (např. v Jave na toto existují tzv. entity classes, u nich by bylo toto rozdělení více podobné struktuře DB, což v PHP zařídit jen tak nepůjde). Dědičnost se definuje tak, že mám jednoho předka, který obsahuje vlastnosti, které se mi budou hodit i ve třídě, která je dědí. Pokud by se mi stalo to, že budu dědit z třídy, která obsahuje vlastnosti, které nebudu nikdy potřebovat, je dědičnost navržena špatně.

Tento článek berte spíše s nadhledem, opravdu se domnívám, že dědičnost je tak záludná záležitost, že bych se na ni na začátku úplně vykašlal. V pozdějších článcích se k tomto tématu vrátím a ukážu, jak něco takového využít v praxi. Příklady, které jsem zde uvedl nejsou úplně nejtypičtější, ale jistě lepší, než ukázky typu: Matka => Dcera, které postrádají použitelnost v praxi.

Příště už o něčem jednoduchém, viditelnosti a klíčových slovech static, final, apod.

neděle 4. března 2007

Proč jsem tolik nadšený z Javy?

Jako každý správný programátor jsem i já velice líný člověk. Ano, přehnanou pílí z Vás programátor nikdy nebude. Důvodem není to, že by programování byla jednoduchá věc, kterou se stačí naučit a pak jen aplikovat, ale proto, že hledáte stále lepší a lepší řešení, které by Vám usnadnilo další vývoj.

Když to převedu do praxe:
Představte si, že vedle sebe posadíte 10 lidí (kteří mají základní znalosti s prací na PC) a dáte jim za úkol napsat v Excelu čísla od 1 do 30. První skupina lidí si sedne a začne psát čísla od 1 do 30. Možná budou i rychlejší, jelikož nemusí nad ničím přemýšlet. Druhá skupina lidí si řekne, že je to moc práce a začne hledat způsob, jak si práci usnadnit. I když zadaný úkol nestihnou v časovém limitu, budou jistě produktivnější. Jen si představte, že byste po těch pracovitých lidech chtěli, aby Vám napsali čísla od 5 do 1000. Kdo myslíte, že poté zvítězí? :)


Tímto příkladem jsem chtěl jen nastínit, že programování není o velké dřině, ale o neustálém přemýšlení nad tím, jak si svou práci co nejvíce usnadnit a zároveň přizpůsobit natolik, abych při nějaké změně nemusel brečet u šéfa, že je to strááášně složité a v podstatě nemožné :)

Vrátím se ale zpět k tématu tohoto článku. Proč jsem vlastně tak moc nadšený z Javy?

Důvod jsem již popsal, jsem líný člověk a nechci svůj mozek vyčerpávat věcmi, které jsou jednoúčelové. Stále porovnávám Javu s PHP. Vím, že porovnávat tyto dvě odlišné technologie je nesmysl, ale toto srovnání dělám na základě vlastních zkušeností a snažím se porovnat jejich použitelnost pro mou práci.

Po získání základních znalostí o objektech jsem měl v PHP problém je nějakým způsobem aplikovat do praxe. Základní API je celé procedurální a v rozjetém projektu jsem nebyl schopen nasadit žádný PHP framework, který by mi mohl mou práci usnadnit. Vydal jsem se vlastní cestou a napsal si svůj vlastní framework na ORM, DAO, Models, Views. Sice nic extra, ale pro mé účely postačující. Jenže... Co dál můžu v PHP chtít dělat, když jsem vázaný na webový kontejner Apache httpd, který musí být navíc natolik odlišně nakonfigurovaný, že se z aplikace stějně stal nepřenositelný moloch. Navíc další využití v menších projektech bylo téměř nulové. Práce s daty také žádný šlágr. Stálé psaní toho samého. Ani IDE (Eclipse a PDT) neposkytuje takový komfort jako v jiných jazycích.

Objekty jsem se hned od začátku učil na Javě, takže jsem věděl, že je to jazyk, který se drží nějakých zásad a má striktní typovou kontrolu, která mě drží na správné cestě a nevede do slepých uliček. Osobně jsem se ale do vývoje v Javě bál více pustit, protože přece jen nejsem žádný guru v oblasti objektů a programováním se zabývám tak 3 roky. Jenže teď jsem v práci dostal za úkol udělat aplikaci na tištění nějakých kartiček, která by běžela pouze na jednom PC a nebyla přes http.

Tak jsem se teď více vrátil k Javě a dělám Swing aplikaci, kterou mám z větší části hotovou. Když jsem zjistil, že mohu použít JPA i ve standalone aplikaci, byl jsem nadšený. Vím, že pak mohu vzít část tohoto projektu a rozjet ho jako webovou aplikaci. Mohl bych toto udělat v PHP? Asi ano, ale dělat v PHP pod GTK by byla jistě dobrá onanie.

I když nejsem žádný přeborník v Jave a většinu věcí zatím dohledávám po netu či píšu na konferenci na java.cz (za odpovědi ještě jednou děkuji), tak jsem schopen všechny překážky přeskočit (ovládání swing aplikace přes události, tisk, napojení na MySQL, atd. atd.), což mě vede k závěru, že už mi chybí jen zkušenosti, abych byl více produktivní v tomto jazyce.

Nadšený jsem zejména z věcí jako je Java Persistence API, díky čemuž objektově namapuji relační databázi a pak již pracuji s objekty a všemi základními vlastnostmi jako je dědičnost či polymorfismus. Navíc nemusím nic definovat v XML, ale hezky si tvořím anotace. Další věcí budiž Swing pro desktop, který je pomocí NetBeans tak snadno naklikatelný, že se jedná spíše o malý Photoshop :). JSF framework pro web. aplikaci mi zejména po použití navigátoru a různých vlastních komponent přišel jako geniální nástroj pro web. Také celé API Javy je natolik rozsáhlé, že snad všechno je v něm již implementované. Samotné standardní frameworky od Sunu jsou na tolik dobré úrovni, že zatím nepotřebuji nic jiného.

Co se týče vlastních zdrojů, musím zde ještě jednou zmínit portál java.cz a jeho emailovou konferenci. Jsem rád, že jsou zde inteligentní lidé a neřeší se zde věci typu: jak vypsat hello world. Dalším dobrým zdrojem jsou přednášky o Javě, které lze nalézt na http://avc.sh.cvut.cz. Než je člověk schopný začít číst z manuálu, také doporučuji tutoriály na netbeans.org. Ukázkové příklady lze nalézt na http://www.exampledepot.com/egs/index.html.

Zdrojů je vážně spousta, člověk musí jen hledat :)


Dobrým zdrojem informací jsou samozřejmě také knihy. Osobně jich o Javě vlastním pět. Ale o těch zase někdy příště. Tak co? Už jste dopsali čísla od 5 do 1000? :)

pondělí 12. února 2007

OOP v PHP 3 - interface

Interface (rozhranní) je jedna z věcí, která je často přeceňována nebo nedoceňována. Oč vlastně jde?

Představte si, že se dostanete do situace, kdy budete potřebovat určit, že objekt "umí" něco, co se od něj očekává, ale nejsme si jistí, zda to tak je :)

Uvedu příklad:
Mám objekty manželka, děti, papoušek, pes a tchýně. Všechny objekty mohu považovat za součást rodiny. Problém nastává ve chvíli, kdy bych potřeboval vědět, kdo z uvedených rodinných příslušníků umí vařit. Vaření si mohu představit jako metodu, která mi provede danný úkon a vytvoří (vrátí) objekt jídlo.

Toto je klasický příklad, kdy mohu použít (implementovat) interface. Nejdříve si vytvořím vlastní interface, které bude obsahovat metodu uvarJidlo().

interface UmiVarit
{
public function uvarJidlo(Jidlo $jidlo);
{
?>


Nyní mám rozhranní, které je potřeba implementovat na ty třídy, které budou moci vařit jídlo.

class Manzelka implements UmiVarit
{
public function uvarJidlo(Jidlo $jidlo)
{
return "manzelka uvarila: ". $jidlo->getNazev();
}
}?>


Takže nyní, když zavolám objekt (rodinného příslušníka), jsem schopen určit, který z nich vařit umí a který nikoli.

$rodina[] = new Manzelka();
$rodina[] = new Tchyne();
$rodina[] = new Pes();
foreach($rodina as $val) {
if($val instanceof UmiVarit) {
echo "umi varit: ". $val->uvarJidlo(new ChlebaVeVajicku());
}
}
?>


Interface můžete chápat jako svou vlastní kontrolu, kde si programátor označuje jednotlivé třídy podle toho, co mají umět. Myslím si, že úplnému pochopení, k čemu vlastně interface mohu využít a jak použít je otázkou praxe. Jak se říká: nic se nemá přehánět. A to platí i zde. Na druhou stranu, ignorace implementování rozhranní vede k chaosu a nižší funkčnosti.

Co se týče pravidel, jsou zde jasně danná specifika:

  • interface může obsahovat konstanty a veřejné metody

  • třída implementující interface musí obsahovat metody podle interface

  • třída může implementovat více rozhranní, které se oddělují čárkou (např. UmiVarit, PrepinaTelevizi)



Samotné PHP obsahuje několik předdefinovaných rozhranní, z nichž nejzajímavější je Iterator.

Tak by bylo k interface vše. Samozřejmě, dalo by se zde napsat spoustu dalších možností a využití, ale stačí, když si budu pamatovat, že Interface usnadňuje a označuje třídy tak, abych byl schopen použít jejich specifické vlastnosti.

Příště již ke zmíněným abstraktním třídám a dědičnosti, která je asi tím nejsložitějším tématem v OOP vůbec.

Když programátor založí a řídí firmu

Jako malý jsem chtěl být popelářem. Ani ne tak proto, že bych měl nějaký zvláštní vztah k odpadkům, ale hrozně se mi líbilo, jak...