Ad IScart: Takže to chápu tak, že to uděláte jako
Televize -<Iskart>- Multiplexor -<Iskart>
-<Iskart>
-<Iskart>
A jak pak třeba uděláte volbu, který kanál na televizi pustit? To bude řešit ten multiplexor? A když budete chtí přidat HDMI, tak předpokládám musíte měnit definici multiplexoru? Nebo pro každé rozhraní bude mít televize vlastní multiplexor - takže budu muset měnit i samotnou televizi?
A před něj strčím objekt multiplexeru, kterým to budu přepínat a který zvládne těch rozhraní více klasicky funkcí getRozhraní(int index). Mám pak větší volnost.
Ne, IMHO máte zaděláno na chybu. Je večer, koukáte se na nejnovější epizodu seriálu přes settopbox. Přijde malej klučina, kterej neví nic o tom, že televize má více scartů (tedy že tam je ještě multiplexor) a vezme scart od videa a zapojí ho do televize do volného konektoru (použije rozhraní IScart od ITelevize). No a co udělá televize? Začne mixovat data z multiplexoru s daty ze scartu. Nebo přepne rovnou na to video. ale to by reálná televize neudělala.
Tím, že implementujete rozhraní IScart jak u televize, tak i u multiplexoru prostě není jasné, co se má kam připojovat - tímto řešením jste vytvořil zbytečný zmatek.
----
Já bych to řešil takto: Mám televizi. Ta má nějaké konektory. Z těch tečou do televize různá data, takže interpretace těch dat je v podstatě záležitost "konektorů" (každej má jiné). No, a když jsem to takhle popsal, tak už je návrh jasný:
ITelevize {
public:
IKonektor getKonektor(typKonektoru, pozice=0)
//metody pro komunikaci s konektorem
void prijmiVideoData(IKonektor, data)
void prijmiAudioData(IKonektor, data)
}
IKonektor {
bool zapocniPrijem() //konektor začne posílat data televizi
}
IHMDIKonektor extends IKonektor
{
void prijmiPaket();
}
IDsubKonektor extends IKonektor
{
void prijmiRGB();
}
IScartKonektor extends IKonektor
{
void prijmiRGB();
void prijmiKompozit();
void prijmiAudio();
}
nevím, jestli to co teče DSubem je totéž, co teče skatem, pokud jo, pak by ještě mělo být rozhraní IRGBKonektor, z kterého by se podědil jak scart, tak RGB.
No a výhody: pro vytvoření televize s jiným rozhraním nemusím vůbec šahat do televize. Pouze vytvořím a implementuji nové rozhraní pro nový konektor (display port). Do televize musím šahat pouze, pokud televize má umět něco více. Pak ale v podstatě to už není ta stará televize, ale např. televize s teletextem, takže v tu chvíli není nic divného na tom, že musím tu televizi upravit (a pravděpodobně podědit nové rozhraní).
Mohu vytvořit televizi s jedním, třemi scarty,sedmi scarty a vždy bude jasné, co kam zapojit a televize se furt bude chovat tak jak má.
A celý tento podle mne čistý návrh plyne z toho, že se na rozhraní koukám nikoli na komunikační protokol: to bych opravdu měl televizi přiřadit rozhraní IScart, protože telvize s ním komunikuje, ale jako na entity. Takže pokud má televize scart konektor, tak prostě telvize musí poskytnout patřičný objekt, nikoli rozhraní. Z toho vyplývá mé chápání rozdílu mezi třídou a rozhraním: rozhraní říká CO, třída říká JAK.
---
Bohužel, každého bude zajímat něco jiného.
Ne vždy. A spousta informací bude společných. On už koncept myslivce je zbytečně speciální - správný koncept je IMHO např. vlastník zvířat. Ten poskytuje metody jako jaká mám zvířata apod. Pokud veterinář chce něco speciálního, tak pak vytvořím pro něj nové rozhraní: protože člověk, co k němu chodí je speciální případ člověka, neboť umí speciální dovednost: podat veterináři informace o zdravotním stavu zvířat. Stejnětak člověk cestující přes hranice např, musí umět dát doklady.
Koncept myslivce v podstatě pak zahrnuje těchto x různých schopností. Máte pravdu v tom, že v jedné aplikaci může být potřeba posílat myslivce k veterináři, v jiném nikoli. V tu chvíli opravdu v každém může být pro "myslivce" (naschvál v uvozovkách, protože každý myslivec vlastně označuje něco jiného) jiné rozhraní. To je ale rozdíl proti tomu, když mám v jednom projektu myslivce s jedním psem a v druhém myslivce s více psy. Myslivec s více psy evidentně zahrnuje i myslivce s jedním psem. Ale nemohu vzít myslivce s jedním psem a přidat mu vlastnictví více psů - protože furt ten myslivec bude mít jednoho "privilegovaného" psa navíc.
Mohu samozřejmě jeho metody přepsat tak, aby toho psa navíc integroval do smečky - jenže to mě ve výsledku zabere více práce, než kdybych vzal myslivce bez psa a implementovat v něm metody vlastnictví psů.
Jak jste přišel na to, že nižší vrstva musí znát všechny protokoly nad ním?
Vy tvrdíte, že rozhraní je komunikační protokol, pomocí které daná entita komunikuje s ostatními objekty. Např. switch v ethernetu příjmá data v protokolu TCP/IP (a posílá je dálú Ergo kladívko, měl by implementovat protokol TCP/IP. To je důsledek vaší definice rozhraní - jako komunikační kanál.
Já tvrdím, že implementovat rozhraní znamená být/mít schopnost. Switch nemá schopnost rozumět protokolu TPC/IP, proto nemá toto rozhraní implementovat.
---
Ad název rozhraní. Doporučil bych Vám připustit, že někdo může mít jiný názor a že jedním slovem (např. rozhraní) může každý označovat trochu jiný pojem. A že pokud ten pojem není pevně přiřazen ke slovu (což v OOP není, jinak by nebyly ty sáhodlouhé debaty, který jazyk je ten jediný správně OOP), že se nedá říci, který význam daného slova je správnější. Takže se prosím smiřte s tím, že chápu pojem rozhraní trochu jinak než vy a místo hádek o termíny se pojďte bavit o tom, který z těch významů je praktičtější a proč.
Co se týče psa a štěkání, tak IMHO slučujete dvě věci. Jedno je schopnost přijmout povel ke štěknutí (k zápisu na disk, k ....). Tomu odpovídá dané rozhraní IStekable s meodou štěkni. Druhá věc je pes ten je zpravidla štěkable, proto by měl implementovat dané rozhraní.
Pak mohu vymyslet koncept psa: řeknu, že pes (rozhraní IPes) je zvíře (extends IZvire), které umí štěkat (extends IStekable). Kodkoli teď může vyrobit (implementovat psa) a může mi ho poslat a já budu vědět, co s ním.
No a pak jsou dvě věci. Někdo umí ovládat psy. Takový člověk by nikdy neřek štěkej robotovy, on to umí se psy. Takže komunikuje s rozhraním IPes. Tento koncept je ale užitečný spíše zřídka. Anebo někdo umí dávat povely ke štěkání: pak umí s rozhraním IŠtěkable a je mu jedno, komu ty povely posílá.... a co protistrana dělá.
Váš pojem rozhraní je pak v podstatě specializace mého: schopnost rozumět konkrétnímu protokolu je vlastnost a jako taková může mít své rozhraní. Až na to, že tím, že si přesněji specifikuji, co je rozhraní, vyloučím špatné návrhy. Např. u televize:
Televize rozumí protokolu scartu? No to přece až tak ne: když scart pustím do HDMI, tak tomu nebude rozumět. Ten kdo rozumí protokolu scartu je pouze ten konektor televize.
A mám s minimem námahy (IMHO hodně dobrý) návrh.
Zatímco ve vašem přístupu televize opravdu komunikuje scartem, takže není nic divného na tom, aby toto rohraní implementovala - v tu chvíli se ale dostáváte do problémů a musíte vymýšlet nějaký multiplexor a stejně to nemusí fungovat - kdokoli může narvat signál do televize přímo.
---
Na zbytek už nebudu reagovat, protože už jsem asi desetkrát psal, že mluvím o tom, jak by se měli aplikace navrhovat od začátku a že pokud je návrh na začátku blbej, tak přepsat ho na dobrej je sice akademicky čisté, ale ne vždy možné či nejlevnější řešení.