Byla vydána beta verze openSUSE Leap 16. Ve výchozím nastavení s novým instalátorem Agama.
Devadesátková hra Brány Skeldalu prošla portací a je dostupná na platformě Steam. Vyšel i parádní blog autora o portaci na moderní systémy a platformy včetně Linuxu.
Lidi dělají divné věci. Například spouští Linux v Excelu. Využít je emulátor RISC-V mini-rv32ima sestavený jako knihovna DLL, která je volaná z makra VBA (Visual Basic for Applications).
Revolut nabídne neomezený mobilní tarif za 12,50 eur (312 Kč). Aktuálně startuje ve Velké Británii a Německu.
Společnost Amazon miliardáře Jeffa Bezose vypustila na oběžnou dráhu první várku družic svého projektu Kuiper, který má z vesmíru poskytovat vysokorychlostní internetové připojení po celém světě a snažit se konkurovat nyní dominantnímu Starlinku nejbohatšího muže planety Elona Muska.
Poslední aktualizací začal model GPT-4o uživatelům příliš podlézat. OpenAI jej tak vrátila k předchozí verzi.
Google Chrome 136 byl prohlášen za stabilní. Nejnovější stabilní verze 136.0.7103.59 přináší řadu novinek z hlediska uživatelů i vývojářů. Podrobný přehled v poznámkách k vydání. Opraveno bylo 8 bezpečnostních chyb. Vylepšeny byly také nástroje pro vývojáře.
Homebrew (Wikipedie), správce balíčků pro macOS a od verze 2.0.0 také pro Linux, byl vydán ve verzi 4.5.0. Na stránce Homebrew Formulae lze procházet seznamem balíčků. K dispozici jsou také různé statistiky.
Byl vydán Mozilla Firefox 138.0. Přehled novinek v poznámkách k vydání a poznámkách k vydání pro vývojáře. Řešeny jsou rovněž bezpečnostní chyby. Nový Firefox 138 je již k dispozici také na Flathubu a Snapcraftu.
Šestnáctý ročník ne-konference jOpenSpace se koná 3. – 5. října 2025 v Hotelu Antoň v Telči. Pro účast je potřeba vyplnit registrační formulář. Ne-konference neznamená, že se organizátorům nechce připravovat program, ale naopak dává prostor všem pozvaným, aby si program sami složili z toho nejzajímavějšího, čím se v poslední době zabývají nebo co je oslovilo. Obsah, který vytvářejí všichni účastníci, se skládá z desetiminutových
… více »Druhá verze je momentálně doporučovaná pro veškeré nové projekty, neobsahuje některé chyby předchozí verze a přidává spoustu nových možností – hodně lidí už nazývá D2 prostě "D". Seriál počítá s tím, že čtenář má alespoň základní znalosti programování a jazyka C, popř. C++.
Jazyk D se objevil v roce 1999 a jeho autorem je Walter Bright ze společnosti Digital Mars. Postupně vznikla menší komunita, ale jazyk stále není dost rozšířen, protože specifikace verze 2.0 není finální a kompilátory stále mají několik much.
Specifikačně, D je multi-paradigm, s podporou imperativního programování jako v C, objektového/generického/meta jako v C++, i funkcionálního a konkurentního. Hlavními zdroji inspirace jsou C, C++, Java, Python, Ruby, C# a Eiffel. I když je D high-level jazyk, podporuje i kompletně low-level přístup, včetně inline assembly.
D používá statické/silné typování a podporuje všechny Cčkové POD typy. Imperativní programování je velmi podobné Cčku, objektový systém přebírá z Javy (nemá vícenásobnou dědičnost, místo toho používá interfaces/mixins), modulový systém je podobný Pythonu. Kromě toho se inspiruje z velké části C++.
D je obecně použitelný a výkon výsledné binárky by měl být srovnatelný s Cčkem.
Kromě toho má D garbage collector, takže si programátor nemusí sám uvolňovat paměť (i když může a gc může být i kompletně vypnuto). Kromě toho je D kompatibilní s C ABI, takže se dá přímo linkovat proti knihovnám napsaným v C (definice prototypů se uzavírají v bloku extern(C)). Kvůli systému modulů nepodporuje D hlavičkové soubory a neobsahuje preprocesor, vše se dá dělat přímo v jazyce.
Momentálně má D dvě verze, D1 (stabilní specifikace) a D2 (vývojová specifikace). Digital Mars doporučuje používat pro nové projekty D2, protože se poučilo z některých chyb D1 a není s D1 plně kompatibilní.
Kompilátorů je několik, hlavní jsou čtyři:
dmd – oficiální kompilátor od Digital Mars. Je vcelku malý (o dost menší než třeba gcc). Tvoří jej dvě části, backend a frontend. Nevýhoda je v proprietární licenci backendu (zdrojový kód je dostupný a je možné do něj přispívat, ale jeho licence nedovoluje redistribuci). Frontend je licencovaný pod GPL v2. Většina ostatních kompilátorů využívá DMD frontend. V době psaní článku měl dmd jednu nevýhodu, a to že neumí tvořit sdílené knihovny – nepracuje správně s PIC registrem.
gdc – využívá gcc backend a dmd frontend. Je to asi nejpoužitelnější D kompilátor, funguje i tvorba sdílených knihoven. Je aktualizován pokaždé, když vyjde nová verze DMD. Podporuje obě verze jazyka.
ldc – využívá llvm backend a dmd frontend. Verze pro D1 je dobře použitelná, verze pro D2 je ve vývoji a v době psaní článku neuměla část standardní knihovny jazyka.
sdc – D2 kompilátor napsaný v D. Je ve vývoji a zvládá jen několik testů.
Kromě toho ještě existoval D2/.NET komilátor kompilující do CLR bytekódu, ale projekt je momentálně neaktivní. Ve většině kompilátorů jsou podporovány všechny hlavní platformy. Seriál je psaný na FreeBSD x64.
Standardní knihovna D se jmenuje Phobos a je dostupná pod Boost licencí. V D1 byla dost omezená a plná chyb, a tak vznikla knihovna Tango, která je dobře použitelná. Nakonec to vyústilo v to, že něco používalo Phobos a něco Tango a obě byly mezi sebou nekompatibilní.
V D2 se tohle vývojáři snažili řešit a vznikl Druntime, runtime knihovna pro D (též dostupná pod Boost licencí). Ta poskytuje ty úplně základní věci jako práci s vlákny, garbage collector apod. Pracuje se na portu Tango do D2, ale Phobos je už dobře použitelná knihovna. Tango i Phobos v D2 by měly být v budoucnu dobře kompatibilní díky druntime.
Seriál se bude zabývat knihovnou Phobos v D2. Oproti např. stdlib v C++ poskytuje Phobos velké množství funkcí, které jsou v C++ normálně doplňovány např. Boostem (JSON parser, kryptografie, curl, threads, URL, XML parser a další).
Naprostá většina seriálů o programování začíná slavným „hello world“ a
já budu konzervativní a výjimku neudělám
Zápis je velmi podobný Cčku/C++.
/* program vypíše "hello world!" do konzole */ import std.stdio; void main() { writeln("hello world!"); }
Tento kousek kódu ukazuje hned několik vlastností jazyka. Klíčkové slovo import slouží k načtení modulů (o modulech budu psát v pozdějších dílech seriálu). V našem případě importujeme modul std.stdio, což je I/O část standardní knihovny Phobos.
Veškeré programy psané v D obsahují funkci main
, stejně
jako v Cčku. Tato funkce je zavolána když program spustíme. Oproti C,
main může být i typu void
, v tom případě vrací program
vždy nulu. Stejně jako v C ale může být typu int
a vracet
hodnoty. Kromě toho může brát argumenty int argc, string[] argv
,
kde stejně jako v C argc je počet argumentů a argv je pole s argumenty
(včetně nultého argumentu!). V našem případě z main voláme funkci writeln
,
která vypistuje neformátovaný text zakončený \n
. Knihovna
samozřejmě obsahuje i spoustu jiných I/O funkcí, ale o těch později.
Ty jsou identické s C99/C++ s přídavkem vnořených komentářů. //
je jednoduchý řádkový
komentář, /* */
je blokový komentář a kromě toho umí i
vnořené blokové komentáře pomocí /+ /+ +/ +/
.
Příklady:
// řádkový komentář /* * část blokového komentáře */ /+ + komentáře s vnořováním /+ + vnořený komentář +/ +/
V tomto je D velmi podobné C/C++. Obsahuje všechny C(++) POD typy plus několik svých. Některá klíčová slova ale chybí, některá jsou nová a kromě toho jsou zde i nové typy a některé stávající mají trochu rozdílné chování. Začneme s těmi základními.
bool mybool; // má automaticky hodnotu "false" mybool = true; mybool = 1; // stejné jako true mybool = 0; // stejné jako false int myint; // hodnota 0 myint = 150; myint = int.max; // maximální hodnota /* v D neexistuje klíčové slovo "unsigned", místo toho mají unsigned typy prefix "u" */ uint myuint; // 0 // myuint = -1 // nejde! myuint = uint.min; // teď je hodnota 0 short myshort = 100; long mylong = myshort; byte b = 0xF; // 15 ubyte ub = 255; // maximální hodnota float f; // hodnota float.nan f = 3.14; /* přetypování */ int casted = cast(int) f; // ořeže hodnotu když je třeba double dbl = f * 2; /* typ real v D je desetinné číslo s největším rozsahem povoleným hardwarem */ real r = 11111111111111.156; /* imaginární členy komplexních čísel */ ifloat if; // hodnota float.nan + i idouble id; ireal ir; /* komplexní čísla */ cdouble cd = 2 + 16i; cfloat cf = cast(cfloat) cd; // ořeže hodnotu pokud je třeba char ch; // unsigned UTF-8 znak, hodnota 0xFF ch = 'f'; wchar wch; // unsigned UTF-16, hodnota 0xFFFF dchar dch; // unsigned UTF-32, hodnota 0x0000FFFF /* řetězce jsou de facto pole znaků jako v C – více v kapitole o řetězcích a polích */ string str = "hello"; // jako const char* v C immutable(char)[] str2 = "world"; // alternativní zápis pro string char[] str3 = ("mutable hello").dup; // možno měnit, jako char* v C char[] str_mutable = str.dup; // jako strdup() v C /* pole */ int[] arr = [ 5, 10, 15 ]; assert(arr.length == 3); arr.length = 4; // takové pole je možno rozšířit arr[3] = 20; int[3] arr; // statické pole int[] arr = new int[](10); // dynamické pole s předalokovanou velikostí /* asociativní pole – hashtable */ int[string] harr = [ "foo":5 ]; harr["bar"] = 10;
Tento kus kódu ukazuje několik dalších vlastností jazyka. V dalších kapitolách se jimi budeme zabývat podrobněji (např. poli).
Výrazy v D se zapisují opět podobně jako v C(++). Jsou dostupné všechny standardní operátory: jak aritmetické, tak bitové i podmínkové. Nejlépě to objasní pár příkladů:
int foo = bar; foo += 5; // přičte 5 foo -= 5; // původní hodnota foo foo *= 2; // dvojitá hodnota foo foo /= 2; // zpět na původní hodnotě foo |= 2; // bitové OR foo <<= 2; // levý shift /* inline podmínky */ foo = (bar == 5) ? 10 : 15; /* pokud se vyhodnotí jako false, ukončí program */ assert(foo == 10, "chybová zpráva"); /* AND, OR */ assert(foo == 15 && bar != 20 || meh == bah); /* bitové výrazy */ x = y | 5; // OR y = x & 5; // AND z = y ^ x; // XOR /* komplexní čísla */ assert(cx == cy); // stejné jako assert(cx.re == cy.re && cx.im == cy.im); /* null se používá s objekty */ class C; C c; assert(c == null); // neplatné, porovnává se obsah, null žádný nemá assert(c is null); // správně
Všechny operátory je možné přetěžovat, více v kapitole o třídách. D podporuje také mixins. Používají se takto:
assert(mixin("5 + 10") * 2 == 30);
To se hodí např. při preprocesingu, když má programátor nějakou šablonu, kterou potřebuje zakompilovat do binárky. Více v kapitole o modulech a importu.
Zápis podmínek, cyklů apod. je standardní:
if (x == 10 && y == 5) { /* true */ } else if (y == 15 && x == 20) { /* true */ } else { /* false */ } for (int i = 5; i < 10; i++) { dofoo(); } while (i < 10) { i++; } do { bar(); } while (x == 10)
Rozdíl je trochu v použití switch. Oproti C a C++ je možné použít stringy u case:
string a = "hello"; switch (a) { case "hello": break; case "world": break; default: break; }
Kromě toho má D i foreach:
char[] mystr; foreach(int idx, char ch; mystr) { writefln("mystr[%d] = '%c'", idx, ch); } int[string] myharr; foreach(string key, int value; myharr) { ... }
Výjimky jsou též podporovány:
try { try { throw new Exception("first"); } finally { throw new Exception("second"); } } catch (Exception e) { writefln("Caught %s", e.msg); }
Kromě toho fungují i break, continue, goto a další z C.
Tímto bych asi ukončil první díl seriálu. V dalším díle se budu zabývat funkcemi, poli, řetězci, popř. objekty. Na této stránce je mnoho dalších užitečných informací o jazyce, včetně kompletní dokumentace ke knihovně Phobos, takže je to určitě dobrý cíl dalšího studia. Tento seriál není kompletním „návodem“ jazyce, ale spíš takovou pomocí, jak se v D zorientovat a jak s ním pracovat.
Nástroje: Tisk bez diskuse
Tiskni
Sdílej:
Obj-C ? Takze bude KERNEL-ULTRAS applikace pro iPhone?
D je programovací jazyk, jehož záměrem bylo „C++ done right“To mi připomíná Subversion („CVS done right.“)...
#include <stdio.h> #include <complex.h> int main(void) { double complex a = 2+3*I; double complex b = 1-2*I; double complex c = a * b; printf("%f %f\n", creal(c), cimag(c)); return 0; }
To je sice hezké, ale pořád mi to přijde multiplatformní asi jako pouštět hru pro Windows ve Wine.Což vzhledem ke věcem jako je winelib, nebo i obyčejnému zapouzdření wine do skriptu, není vůbec špatné. Ovšem pokud ta hra bude psána jako multiplatformní (což nevylučuje, že jednou z cílových platforem jsou windows).
//
) do konce řádku (a to D má), absolutně k ničemu.
/* Začátek komentáře /* Předchozí komentář */ Konec předchozího komentáře, který ukončí blok komentářů */ Zamýšlený konec komentáře, ve skutečnosti chybavs
/+ Začátek komentáře /* Předchozí komentář */ +/ Konec komentářeBTW: Autor ještě zapomněl zmínit dokumentační komentáře.
char ch; // unsigned UTF-8 znak, hodnota 0xFFUTF-8 znak (čo to vlastne je?) asi nemôže mať hodnotu 0xFF...
import std.stdio; void main(){ char ch; writefln("0x%x", ch); }
bystrousak@kitakitsune:~/Plocha$ rdmd char_test.d 0xffNěkolik dalších informací třeba v oficiální dokumentaci: Types, Porovnání C++ a D stringů.
může:
http://ideone.com/NGbmt
http://www.eki.ee/letter/chardata.cgi?ucode=00FF
http://www.utf8-chartable.de/
assert(mixin("5 + 10") * 2 == 30);
WTH? Tady mixiny jsou asi něco jiného než třeba v Ruby, ne? Já bych to pojmenoval "eval" Autor poukazuje na linkovatelnost k objekovým souborům jiného kódu, ale zároveň dodává, že prototypy je nutné obalit do bloku extern C. To ovšem znamená, že se překladač používá pro symboly v objektu jiné názvy, než které používá programátor v D.
Táži se tudíž, jestli specificikace stanovuje name space mangling, nebo jestli to je ponecháno na libovůli překladače, jako to je u C++, pročež není možné míchat knihovny přeložené různými překladači (nebo dokonce jejich verzemi)?
foreach
by som určite spomenul i foreach_reverse
a mixiny by som ponechal na samostatný diel.
V poslednom príklade sú špatné úvodzovky:
throw new Exception(„second“);
Dík za seriál.
Z vaše výčtu v příkladech vidím jenom kontejnery přímo v jazyce, tady konkrétně hashtable, což považuji naopak za významné pokurvení jazyka, a lehkou zmínku o GC, který, když už teda na něm někdo trvá, lze mít v C++ také (ne, o smart_ptr nemluvím).
Ale třeba to bude v dalších dílech lepší.
IMO, kontejnery v jazyce jsou lepší přístup, ale to je asi věc osobního vkusu
Pro jednodušší programy je to samozřejmě výhoda, syntaxe je přehlednější, pohodlnější a názornější. Ale časem se dostanete do situace, kdy budete potřebovat nějaký kontejner, který v jazyce není. A pak se nutně ty ručně dopsané budou syntaxí lišit od těch standardních. Výhoda kontejnerů ve standardní C++ knihovně je, že si můžu napsat vlastní rb_map
, který interně používá RB strom, ale navenek se chová stejně jako standardní std::map
, takže v případě potřeby stačí vyměnit typ v deklaraci, přidat jeden #include
a na kódu nemusím měnit vůbec nic.
Mají a jsou super, nicméně vícenásobná dědičnost není zlo, ale umožňuje někdy výrazně méně psaní, když to je potřeba.Nevšiml jsem si.
Prostě nežeru myšlenku: „Interface nesmí nikdy obsahovat nějakou implementaci“.Tak to se shodnem. Já neměl namysli nutně pouze abstraktní interface. Ale ve většině případů s ním vystačím. Při dobrém návrhu se dá funkcionalita interface vyhodit do samostatné třídy, takže i absence implementace se dá obejít. Přijde mi to jako menší prasárna než řešit při vícenásobné dědičnosti problémy s vícenásobným předkem.
Chtělo by to jazykovou podporu pro delegaciTo by imho bylo dědičnosti velice podobné (onehdá se o tom vedl flejm). Byla by to vlastně dědičnost, akorát s trochu jinými pravidly přístupu.
Chtělo by to jazykovou podporu pro delegaci, ale to bohužel zatím nikdo nemáNevím přesně jakou formu podpory máte na mysli, ale některé jazyky dovolují rozšiřovat syntax, takže by neměl být problém si tu podporu dodělat.
IMHO odstranění vícenásobné dědičnosti je jen první krok směrem k nevyhnutelnému odstranění jakékoli dědičnosti,IMHO vyvráceno praxí.
class A { B b expose *; // řekněme, že B má metody m1 a m2 C c expose m3, m4; D d expose * but m5, m6; // řekněme, že D má metody m5, m6 a m7 }Triviální desugaring vypadá takhle:
class A { B b; C c; D d; m1() { b.m1(); } m2() { b.m2(); } m3() { c.m3(); } m4() { c.m4(); } m7() { d.m7(); } }Snaha vystavit metodu se stejnou signaturou z víc delegátů by vedla k chybě při překladu. Má to pár zajímavých sémantických problémů: Kdy se inicializují
b
, c
a d
? Smí se za běhu změnit? A vynull
ovat? Jak by se ta změna projevila v ostatních vláknech?
Jedna věc, která se mi líbí na traitech, kterou takovýmihle triviálními delegáty neuděláš: Trait smí deklarovat abstraktní metodu, kterou musí "implementující" třída definovat. Takže je tam ta vazba vlastně obousměrná. Je to užitečné, ale nejsem si jistý, jestli to nemá nějaké vlastní problémy.
Další související věc by byla jazyková podpora pro dependency injection class A { B b = new B() exposing *; // řekněme, že B má metody m1 a m2 C c = new C() exposing m3, m4 { public int m4 { // implementing abstract method return 42; } } }Aby to bylo konzistentní, tak by metoda m4 asi neměla vidět nic ze symbolů v A. Jenže to právě ty mixed-in metody v Ruby dělají, což? Případně by m4 mohla definovat obalovací třída A, hmmm, máš pravdu, je to zajímavý problém.
Aby se s tím dalo pracovat, tak by to ještě chtělo taková ta implicitní rozhraní, co má Go: třída A podporuje taková rozhraní, pro něž jsou všechny potřebné metody vystavené.Jasně. Existuje totiž jeden rozdíl, o kterém už jsem na ábíčku několikrát mluvil, ale spousta lidí si ho pořád neuvědomuje, rozdíl mezi podtypem a podtřídou. Zdálo by se, že v mém příkladu výše bych nemohl napsat
B b = new A()
, protože A přece není podtřídou B. To sice není, ale je jejím podtypem (viz substituční princip Báry Liskovové). To lze zjistit automaticky, jako v tom Go, nebo lze vyžadovat, aby to programátor deklaroval. Nemám vyhraněný názor na to, co je správné.
A k těm abstraktním metodám z traitů, v čem je problém?Já to asi řekl špatně. Traity umožňují něco takového:
trait T { abstract int m1(); // jenom třída, která má m1, může includovat T int m2() { return 2 * m1(); } } class X with T { // to je OK int m1() { return 1; } } class Y with T { // to je chyba při překladu, Y nemá m1 }Je to taková rozumnější forma dědičnosti, která netrpí některými problémy (narozdíl od mixinů). Ale máš pravdu, mohli bychom uvažovat abstraktní třídy bez dědičnosti, a ve třídě, která by na někoho takového chtěla delegovat, bychom ty abstraktní metody museli dodefinovat. Ta dodefinovaná metoda by naopak měla přístup k vnějším symbolům, a měli bychom to kompletní. To možná není špatný nápad. Delegát může mít svůj stav (trait ne; mixin ano, ale ten stav se dědí, zatímco tady by byl zapouzdřený), to je užitečné, vystavit z něj jde jenom metody, kolize je třeba řešit ručně, to by mohlo fungovat.
No, jestli považuješ agregaci za jiný druh dědičnosti, tak samozřejmě. Zrovna tak můžeš považovat dědičnost za jiný druh agregace.No já tadyto žonglování s těmihle pojmy celkově moc nemusím... mně to přijde jako buzzwordy. Ono totiž v praxi je "dědičnost" něco jinýho v C++, něco jinýho v Javě a něco jinýho v C# a tak dále. Každá z těhle implementací má svoje problémy, a tím pádem i svoje (různá) řešení. No a pak říkat, že "Návrhový vzor X bych nahradil Y" je takové mnhoznačné, protože v každým jazyce/prostředí by to způsobylo něco jinýho...
o tom by měl rozhodovat volanýKvůli tomu přece není potřeba rušit konstruktory. Nějakou formu kontruktoru mít musíš...
factory
, která by jediná mohla používat operátor new
, ale to v zásadě nic neřeší a jenom to přidělává bordel. Dependency injection je výborná věc, ale jen na určitou množinu problémů, univerzální řešení to není. Fakt nevím.
Buzzwordy, hmm, a co že toho nejsou plná všechna ta byznys-oryentyd mídia typu ITBiz? OOP byl buzzword, někdy před 20 lety, dneska letí NoSQL, ale dědičnost a agregace? Pojmy mají i svůj význam, proto existují, a že se ti zrovna nechce… no, to není můj problém.Ty pojmy mají svůj význam, ale jen v nějakém konkrétním kontextu. Ne ve filosofické debatě typu "Dědičnost je špatná, měla by se nahradit delegací/agregací/perforací/jánevimčim". Měla by se nahradit v jakém projektu? V linux kernelu? V GUI toolkitu? Ve webovém frameworku? A podobně... Prostě říct, že návrhový vzor X je lepší je jako říct, že operační systém X je lepší. Bez bližšího kontextu to nemá valný smysl.
Konstrukce objektu je hrozně magická operace.Houby magická operace
class A
{
private:
B b::(*); // B má metody m1 a m2
C c::(m3,m4)
{
int m4()
{
// implementing abstract method
return 42;
}
}
D d::(^(m1)); // ^(m1) značí vše krom m1, D má metody m1 a m5
public:
A() :b(new B(...)), c(new C(...))
{
//...
d = new D(...);
}
}
Neříkám, že takhle to je vhodný způsob, jen mě to tak napadlo coby příklad...
Pojmy dědičnost a agregace mají svůj význam v kontextu objektově orientovaných programovacích jazyků.Jo? Takže můžu přístupovat stejným způsobem k třídám v C++, Javě, C# a třeba Objective-C? Neřekl bych...
Ve Smalltalku je AFAIK každá třída potomkem nějaké jiné třídy. A čím potomkem je ta prapůvodní třída, která stojí v kořeni hierarchie dědičnosti?Je bez rodiče. Stejný to je v Object Pascalu - tam mají TObject.
Už chápeš, jakou magii mám na mysli?Ne, to teda nechápu, já tam žádnou magii nevidim...
ale způsob, jak se vytváří objekty a hlavně jak se spojují dohromady do grafu, který tvoří aplikaci, je z praktického hlediska velmi důležitý (proto už jsem tady několikrát zmiňoval DI).S tím naprosto souhlasím. Mohli bychom říct, že aplikace je (z tohohle hlediska) nějaký graf objektů, buď to strom, nebo alespoň DAG, v něm jsou objekty rodičovské, potomci, a mezi nima nějaká "dědičnost" ... teď ale nemyslim tu konktrétní dědičnost známou z běžných OOP jazyků, ale obecně jakoukoli dědčinou, ať už se realizuje pomocí "běžné" dědičnosti, pomocí agregace nebo pomocí jánevím čeho. Pak tam samozřejmě existují všelijaké další vazby... Někteří lidé je rádi pojmenovávají... Takže už zbývá "jenom" to, jak to vyjádřit programovacím jazykem. Já bych osobně nejradši jazyk, který by poskytoval co nejvěší volnost a zároveň obsahoval syntaxi pro realizaci co nejvíce možných způsobů těch vazeb. Čili by asi (částečně) obsahoval nějakou meta-syntaxi. V tomhle se mně právě u D libí operator overloading - poskytuje opravdu velkou volnost.
Mohli bychom říct, že aplikace je (z tohohle hlediska) nějaký graf objektů, buď to strom, nebo alespoň DAGMohl by to být i graf s cykly s tím, že by pak mezi objekty nebyl vztah částečného uspořádání ale jen předuspořádání.
DI to je to, o čem se tak strašně zmateně píše na rootu?To je ono. Mluví se o tom už víc než deset let, ale do světa PHP se to dostalo až teď
Vytvoření objektu by mělo být zavolání metody třídy.A proc? Tohle me vzdycky prislo zbytecne svihle. Konstruktory objektu bych nechal jako normalni samostatne funkce (nikoliv metody objektu/trid/cehokoliv), a bylo by po problemu.
To, že to bývá instance třídy je spíš použitým jazykem a tím, že se Factory nepoužívá na triviální operace.To je naprosto v pořádku. Mezi náma, metoda __new__ v Pythonu má taky schopnost vracet jiný objekt, než o který si uživatel řekl. Takže taky funguje jako factory funkce dokonce má k dispozici stav třídy, tzn třída funguje jako factory objekt. Ale fakt je, že když chci opravdový factory objekt, vytvářím ho samostatně kvůli čistotě kódu.
Vyjadřovací síla všech programovacích jazyků je stejná, ano.To není pravda.
Chtělo by to jazykovou podporu pro delegaci...Pokud jsem to pochopil, tak takovou delegaci umí Delphi (Object Pascal). Funguje to tak, že třída implementuje interface přez nějakou property, která implementuje daný interface. Je ale potřeba co nejdříve (např v konstruktoru) property nastavit na platnou instanci
type
TMyClass = class(TParent, IInterface1)
private
FInterface1: IInterface1;
public
constructor Create;
property Interface1:IInterface1 read FInterface1 implements IInterface1;
end;
Bohužel nevím, jak je to nyní, ale ve Free Pascalu s tímto byly problémy, ale jako jazyková vlastnost je to specialitka. Pascal jsem se časem odnaučil mít rád, ale tohle mě párkrát v C# chybělo.
Pokud se bavíme o tom, že interface má nějakou implementaci, tak to už není interface ve smyslu, že lze vícenásobně zdědit/implementovat pokud není povolená vícenásobná dědičnost.Parse error.
Pokud implementaci vyhodím do další třídy, tak je to právě to psaní navíc jen abych dostál nemožnosti vícenásobné dědičnost, ale principiálně je to „workaround“ a způsobí právě to, že se více píše.Asi jsem to špatně pochopil, myslel jsem, že „psaním navíc“ bylo myšleno zbytečné opakování kódu. Pokud jde o hlavičku jedné třídy navíc, tak pak beru zpět, že se v tomto shodnem. To mě u vícenásobné dědičnosti či interface opravdu netrápí. Mně osobně spíš jako workaround přijde implementace vícenásobné dědičnosti třeba v C++.
A jiném případě se zas musí zapouzdřovat a zveřejňovat a zas je to více psaní (zapouzdření není vždy ten správný přístup, i když bezpečný). Pokud se použije nějaká názvová konvence a používá se to „přímo“ ve „finální“ třídě, obvykle žádné problémy nenastanou, a efektivita je vyšší a čitelnost či přehlednost to neovlivní.Parse error.
Si prostě myslím, že vícenásobná dědičnost není zlo, zlo je když se používá místo „interface“ a její odstranění považuji za zbytečnou obstrukci jazyka.Nikde jsem nepsal, že je. Jen se mi nelíbí vícenásobná dědičnost à la C++, a tím pádem vícenásobná dědičnost ve všech jazycích, které se budou snažit optimalizovat do stejné míry jako C++.
No pokud obsahuje interface nějakou implementaci není to již interface, ale například abstarktní class a tudíž se neimplementuje, ale dědí a pokud nelze dědit vícekráte tak je to stopka, pokud chceme dědit s obou.To už je o něco srozumitelnější. To, že interface má přiřazené už nějaké hotové metody podle mě ještě nutně neimplikuje, že je to abstraktní třída (tzn že to má všechny vlastnosti, co abstraktní třída v daném jazyce). Nejspíš je to mixin.
To psaní: Ano hlavička další třídy, komentáře a volání dané metody a případné nadbytečné předávaní nějakých parametrů - ano to jsem myslelTak kvůli tomu bych se s vícenásobnou dědičností netrápil, pokud nejde implementovat nějak hezky a čistě.
No to je druhý případ psaní navíc, class má používat(dědit) třeba dvě třídy a rozhraní obou tříd má být veřejné. Takže pokud nelze dědit vícenásobně, tak se instance class-ů zapouzdří a buď se zveřejní metoda (getter) jednotlivých instancí (což má své nevýhody). Nebo se jednotlivé fce napíší znovu a jejich obsahem je jen provolání jednotlivých fcí zapouzdřených instancí.No... když vezmu dvě zcela nezávisle vytvořené třídy... a chci od obou dědit... tak budu mít docela problém s kolizemi, ne? Stejně nad tím nakonec budu muset postavit nějaký slušný interface, takže mám za to, že toho psaní navíc tak moc nebude a ta efektivita zdaleka jít do háje nemusí.
class A { public: void delej(); }; class B { public: void delej(); }; class C : public A , public B { public: using A::delej; }; C c; c.delej(); // A::delej() c.B::delej(); // Explicitně chceme delej z B
Asi si zase nadělám pár nepřátel, ale musím konstatovat, že nechápu všechny ty komentáře typu "super článek". Podle mne je ten článek z didaktického hlediska naopak velmi špatný. Tedy aspoň pokud byl zamýšlen jako výukový.
Článek mi připomněl jeden odstrašující příklad, jak by se učit nemělo, v osobě našeho učitele informatiky na gymnáziu (paradoxně zaměstnance KDM MFF UK). Typická hodina vypadala tak, že přišel, prohlásil: "Tak dneska si probereme pole. Pole se deklarují takhle: ...", napsal na tabuli syntaxi a když jsme měli štěstí, přidal i nějaký příklad. Pak nám dal nějaké zadání a nechal nás, ať se snažíme. Přičemž vůbec nevysvětlil, co to takové pole vlastně je a k čemu slouží. Výsledek? Kdo už Pascal uměl, ten se nic nedozvěděl, kdo ne, stejně neměl šanci to z jeho výkladu pochopit, takže byl odkázán na následný výklad od spolužáků.
Proč o tom mluvím? Protože tento článek funguje přesně stejně. Místo aby se začlo nějakým "filosofickým" úvodem o jazyce jako takovém, autor hned začne bez jakéhokoli systému chrlit úkázky, které ani moc neokomentuje, takže nám nezbývá než se dohadovat, jestli to int[string]
je asociativní pole či co, co je to vlastně ten "mixin", proč má "UTF-8" znak maximální hodnotu 255 atd. Prostě jen výčet "podívejte se, co to všechno umí". A stejně jako v předchozím odstavci: kdo jazyk zná, tomu to nic nedá (až na ten příjemný pocit "jo, to znám"), kdo ho nezná, tomu také ne. Prostě to celé působí jako screenshotová "recenze" nové verze distribuce, ne jako výukový článek.
Neberte to jako že vás chci nějak strhat; vlastně jsem se ještě ani nepodíval, kdo je autorem, a záměrně to neudělám, dokud tento komentář neodešlu. Naopak, snažím se vám pomoci, protože nadšené komentáře "super článek" vám nepomohou, ty vás jen utvrdí v přesvědčení, že to děláte skvěle, což bohužel vůbec není pravda. Zkuste se nejdřív zamyslet nad tím, komu je článek vlastně určen, a pak si text procházet ne svýma očima (někoho, kdo jazyk zná a používá), ale očima právě té cílové skupiny (která ho dost možná vidí poprvé). A nepostupujte zdola, tj. od konkrétních ukázek demonstrujících nevysvětlené principy, ale naopak shora, tedy od těch principů, které pak teprve demonstrujete na ukázkách.
Ale neco jsem si presto z clanku odnesl. Ten dort, co kocicka s pejskem pekla byl patrne 'multi-paradigm'Malem jsem smichy spadnul ze zidle.