bubavanek:
nic si z toho nedělej, na todle bychom si měli založit svuj thread. Nicméně pokud si dáš práci a pochopíš, o čem se píše, myslím, že Ti to k něčemu bude, ať už skončíš u C++ nebo ne.
novacisko:
V Javě taky. Co když tu metodu nějaký předek reimplementuje?....
A mohu kontrovat i tím, že ... vždycky tam můžete vrznout tu virtuální dědičnost...
a) No tak napíšu tu reimplementaci. Přeci když přidávám novou metodu, tak vím, co má metoda dělat a kterých tříd se týká. Nemusím ale hrabat do tříd, které tuto metodu dědí a to považuji za podstatné.
Právě to, že při modifikaci třídy musím modifikovat i potomky nepovažuji za vhodnou vlastnost.
b) Např. u agilní metodiky se budu v předcích hrabat furt. Takhle skončím se všemi dědičnostmi virtuálními...
Naučte se C++. Při downcastu nemusíte přetypovávat static_castem (můžete).
Co kdybyste místo předpokládání, že je ten druhej blbej se snažil pochopit, coten druhý píše?
class IA
{
public:
virtual void a()=0;
};
class IB: public IA
{
public:
virtual void b()=0;
};
class A: public IA
{
public:
void a() {};
};
class B: public A, public IB
{
public:
void b() {};
void a() {};
a.cpp: unmodified: line 1
class IA
{
public:
virtual void a()=0;
};
class IB: public IA
{
public:
virtual void b()=0;
};
class A: public IA
{
public:
void a() {};
};
class B: public A, public IB
{
public:
void b() {};
void a() {};
B() {};
};
int main()
{
B* b=new B();
IA* a=b;
}
Tady (na předposlední řádce) přetypovávat musím, jinak kompilace spadne. Právě proto, že pro C++ je IA a IB jiné rozhraní, přičemž ve všech ostatních jazycích se IB bere jako rozšíření IA .
A jestli jste myslel, že můžu použít normální přetypování, tak to sice máte pravdu, ale obecně se C-like přetypování užívat v C++ programech nedoporučuje, anžto může zavléct chybu....
Dálkový ovladač byl použit jako abstrakce rozhraní.
Ale copak je ovladač rozhraní - tedy ve vašem významu (se kterým úplně nesouhlasím) tedy komunikačním protokolem?? Ovladač je entita, která vysílá povely nějakým komunikačním kanálem jiné entitě (televizi).
Nebo si myslíte, že tím, že implementuje třída rozhraní říká, že třída je rozhraním? Toje taky blbina.
IMHO není. Pokud např, objekt implementuje rozhraní ISerializible, pak ten objekt JE serializovatelný. Možná spíše bych volil "se navenek chová jako objekt typu popř. objekt mající danou vlastnost".
Pokud omezím "implementovat rozhraní" na "rozumí komunikačnímu protokolu", vede to imho právě na chyby v návrhu, protože to neodhalí složené objekty. Televize s videem rozumí jak příkazům pro televizi, tak příkazům pro video - takže při vašem přístupu je košér implementovat obě rozhraní. Jak jsem ukázal v minulém postu, pokud to ale implementuju jako objekt, tak se brzy při případných úpravách dostanu do problémů - televizi se dvěma videi tímto způsobem neimplementuji.
Pokud přijmu můj přístup, tak televize není video, video není televize a televize s videem není ani video, ani televize, ale spojení dvou objektů. Takže nechám televizi implementovat rozhraní televize, videu rozhraní videa a není žádný problém.
Proto tvrdím: implementovat rozhraní znamená konstatování, že tento objekt je nějaké povahy (např. být televizí, být serializovatelný atd...).
a)A co stavové protokoly? (rozšíření dalším rozhraní přidá další stavovost, kterou původní rozhraní neumí)
Představte si rozhraní jako port na serveru: Jak to rozhraní pozná, že ta druhá strana, která s tím protokolem komunikuje je stavová či nestavová? Jediná možnost je, že se zašle nějaký příkaz: přepni se do rozšířeného módu. Ale pak to jde implementovat v jedné metodě a nepotřebuji různé metody podle toho kdo volá. Takto se dá koukat např. na IP protokol, kde vždy musí být uvedeno, jestli jde o TCP nebo UDP....
Anebo stavová komunikace používá jiný kanál než nestavová komunikace (např. TCP/UDP). Pak ale přeci nejde o stejné rozhraní.... TCP přeci není totéž co UDP - i když používá "stejná" čísla portů...
b)To že má druhý ovladač stejně barevná tlačítka a tři tlačítka navíc neznamená, že ty barevná tlačítka dělají totéž jako na prvním ovladači
Ale ovladač přeci není rozhraní!!! Ovladač je reálný objekt, nikoli komunikační protokol. Ty dva ovladače budou sdílet stejné vstupní rozhraní "mít tři stejná barevná tlačítka". A pokud dělá každý jinou věc, tak stisk těch tlačítek vyprovokuje komunikaci po jiném rozhraní s ovládaným objektem (nebo lépe po stejném rozhraní - obé bude infra - ale s jiným objektem a jinými kódy).
Vždyť i pokud by byl ovladač rozhraní, tak jak byste implementoval programovatellný ovladač, který umí ovládat padesát různých věcí? To kvůli jednomu objektu budete modifikovat padesát tříd a každé přidávat další rozhraní? I když jak ta televize, tak video i HIFI věž se existencí programovatelné ovladače vůbec nezmění? Furt půjde jen např. vypnout posláním 000, zapnout posláním 001 a přepnout program posláním 100??
Naopak pokud přijmete paradigma, že ovladač je objekt, tak prostě napíšete jeden programovatelný ovladač, který bude umět volat jedno obecné rozhraní IInfraOvladač.
Dokonce se pak může klidně stát, že jeden příkaz zapne televizy, na videu spustí nahrávání a na HIFIvěži vymění CD. A to celé zajistím, aniž bych jakýkoli přístroj modifikoval.
PS: samozřejmě, pokud programuju jednoduchou věc, často ovladač a televizi pro jednoduchost sloučím. Je to ale "berlička", měl bych si být vědiom, že to co dělám je nelegální a v případě implementace např. dvou ovladačů budu muset buďto prasit
(s omluvou: váš přístup :-)), nebo refaktorovat.
Ono v tomto případě je zas ale lepší se vykašlat na ovladač a tvářit se, jako že se ovládá přímo televize. Pokud budu potřebovat více různých ovladačů, tak vždycky mohu dopsat "mezivrstvu".
RAII pattern je v C++ velice oblíbený. V zásadě bych se bez něho nikam nehnul....
To co v javě schází je automatická destrukce (a uzavření). Souhlasím, že to někdy vadí, na druhé straně mám dva typy zdrojů: jedny je potřeba uvolňovat hned, druhé nikoli.
U prvního typu zdrojů je imho chyba spoléhat na RIAA a chytré pointery, když se mají uvolňovat co nejdříve, tak bych je měl opravdu uvolnit hned a explicitně - spoléhat na to, že tento pointer nikam neuteče není moc bezpečné - při další úpravě se situace změní a zdroj se neuzavře.
(Navíc většina chytrých pointerů používá reference counting a tedy reálně hrozí, že dojde k zacyklení a neuvolnění zdroje - ale třeba máte chytřejší implementaci chytrých pointerů?).
U druhého typu jde naopak počkat "až někdy". V tu chvíli mohu použít kombinaci pseudodestruktorů a nějakého sběrného objektu, který na konci programu zajistí uzavření všech dosud neuzavřených zdrojů. Samozřejmě to si musím napsat, ale implementace nebude složitější než chytré pointery v C++.
Takže imho RAII pattern je v javě v podstatě stejně použitelný jako v C++, jen se musí využít toho, co nabízí java a ne k tomu přistupovat jako k C++. Výsledek bude +- stejný: V C++ občas díky zacyklení nedojde k uvolnění zdroje, v javě zas dojde k uvolnění zdroje se zpožděním oproti C++.