Diskuze: Společný předek v listu a Interface
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Tvůrce

Zobrazeno 37 zpráv z 37.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Určitě s jedním předkem. Již jsem někde psal, že interface není nutný a u menších projektů kde je pár tříd bohatě stačí společní předci. Jinak jsem tu o něm napsal docela dost i s tím, k čemu se používá.
Pokud ti nějaká továrna vyrobí objekt neznámého typu a v tom generovaném objektu chceš zavolat nějakou metodu, musí ta metoda být deklarována v interface. Jinak ti překladač bude tvrdit, že objekt takovou metodu nemá.
Všechny třídy, které jsou v té továrně, musí toto interface implementovat.
Ono si to jde jednoduše představit u her na interfacy typu IPohyblivy, IHorlavy, IJidlo a podobně. Mám na to připravenou takovou ukázku, ale v nejbližší době to sem dát nestihnu.
Nějak jsem si nezvykl psát "I" na začátku jména interface. Vždyť ani rozhraní, které jsou součástí jazyka, tam to "I" nemají.
V Javě ne a je to chyba, protože se na první pohled nepozná, jestli to je třída nebo Interface. Proto C# tuto konvenci zavedl a používá ji u všech interfaců.
Takže bych to vlastně měl psát nějak takto:
IKolekce<int> prvocisla = new List<int>();
Interface IKolekce jsem si vymyslel, ale snad je jasné, co tím chci sdělit.
Nějak nevidím důvod, proč bych měl rozlišovat mezi třídou a interface.
Vytvářet si druhou kolekci už jen určitých herních objektů se vyplatí ve chvíli, kdy těch objektů je hodně a potřebuješ urychlit jejich procházení, hlavně pokud je to (procházení celé kolekce)², tam je znát, jestli je to cyklus 10x10 nebo 1000x1000 - třeba když testuješ kolize určitých objektů mezi sebou.
Asi nejběžnější a nejlepší na pochopení použití interfaců je ISerializable - potom u všech objektů, které ho implementují máš funkci, která ti ten objekt převede na pole bajtů a zpět.
Případně třeba INetworkable - podobné, ale nemusíš vždy posílat všechny bajty objektu, ale jen určité, které jsou pro danou zprávu potřeba.
IDisposable - pro objekty, které při zanikání potřebují uvolnit systémové prostředky - třeba zavření connection do databáze, vymazání textury z paměti grafické karty, zavření souboru apod.
Interface se prostě používají kdykoliv potřebuješ nějakou stejnou funkcionalitu od tříd, které si jinak nejsou vůbec příbuzné.
Uh, to je divné použití, kolekce interfacu by byla takhle:
List<ISerializable> seznam = new List<ISerializable>();
Ale David Hartinger myslel spíš asi hlavičku třídy
class Trida : IDisposable, ISerializable, Predek
{
}
To jsem střelil od pasu. V tu chvíli mě nenapadlo nic vhodnějšího. V Javě však běžně píšu
List<int> prvocisla = new ArrayList<int>();
nebo dokonce
Collection<int> prvocisla = new ArrayList<int>();
kde List a Collection jsou interface a ArrayList implementace.
Tak asi nemyslel hlavicku, ale kod, koukam, ze Java rozlisuje predka a interface v hlavicce tridy pomoci slovicek extends a implements.
treba
Vysledek result = ... prirazeni odnekud
kde bys nepoznal, jestli Vysledek je trida nebo interface.
A proč je důležité rozlišit, jestli Vysledek
je třída
nebo interface?
Aha, takhle jsi to myslel, kolekci, ktera je zaroven interface.
Zrovna u tohohle pouziti to tak nevadi, vice je to zrejme kdyz mas kolekci interfaců.
List<int> prvocisla = new ArrayList<int>();
Tohle pouziti nijak nevadi, ale zacne prekazet kdyz budes chtit pouzivat pokrocilejsi funkce ArrayListu, ktere rozhrani List neobsahuje a pridava je az implementace ArrayList - pak budes muset pretapovavat, aby ses k nim dostal (samozrejme pokud v danou chvili vyuzivas jen zakladni funkce, pak to potreba ani nebude).
Přesně tak. V Javě je List
pouze interface, nedají se z
něho dělat instance. Má se používat co nejnižší interface, které
ještě splní naše požadavky, klidně to může být i Object, pokud
potřebuji jen metodu toString. Případně Numeric u čísel.
Třeba proto, že třída a interface je úplně něco jiného. Proto by se to mělo i jinak jmenovat. V Javě je třeba List velmi špatně zvolený název pro rozhraní, tak by se měla jmenovat kolekce.
Díky všem za odpovědi .
Teď jsem došel do bodu, kdy jsem zjistil že to mám mírně špatně
navržený
Sice to můžu
nějak doplácat, ale to nechci, časem to bude ještě horší. Nezbývá nic
jiného než to trochu přepsat. Nastíním problém, možná mi řeknete tip co
a jak. Prostě ještě v tomhle trochu víc plavu a občas si to nedovedu
představit i několik kroků dopředu aby to bylo furt nějak dobře
použitelný. Takže dělám hru, 2D hra z ptačí perspektivy, je to spíše
test "enginu" takže kolize,kamera, světlo, generování mapy ... popíšu
základní třídy které mám. Zatím nepoužívám Interface a právě ho budu
asi muset použít abych to líp oddělil. Spíše to přepíšu tak nějak
hodně
...
Abstraktní třída HitableObject
Obsahuje pouze Rectangle - určuje pozici, kolizi
Obsahuje jedinou metodu - CheckCollision - kontrola kolize
Tuto třídu používám například pro UserComponenty - Button,TextBox...
Třída GameObject : HitableObject
Rozšiřuje HitableObject o Texturu a dvě metody Update a Draw. Třída je
abstraktní.
Přidává vlastnost Solid - určuje, jestli může hráč, střela,... projít
objektem nebo ne.
Pracuju na světle. Světlo funguje tak že mění vlastnosti objektů - Visibility a to na tři stavy: Visible,Explored,NoVisible.
Visible způsobí plnou viditelnost objektu
Explored značí, že jsme už tady byli ale nejsme poblíž, objekt je ztmaven
ale je mírně vidět.
NoVisible - objekt není vidět. Je tam tma.
No předpokládám že by bylo na místě udělat si interface
ILightableObject, který by implementoval enum Visibility a metodu která
změní stav.
Poté si tedy vytvořím třídu jako MapObject (objekt který bude ovlivňován
světlem a je na mapě), která bude dědit od GameObject a bude implementovat
rozhraní ILightableObject.
Poté si tyto všechny objekty naházím ještě do nějaké společnější třídy Map, která bude držet info o mapě a vždy proiteruju všechny objekty ILightableObject a nastavím jim změnu viditelnosti
Je tento nápad správný ? Díky
Rozdíl mezi třídou a interface je v podstatě jen v tom, že třída navíc obsahuje i implementaci.
U kolika tříd bys chtěl implementovat ILightableObject?
No třídy, které představují mapu - zdi, podlaha ... dále samozřejmě na různé objekty jako jsou truhla, sudy a nakonec nepřátele a interaktivnější objekty.
Interface nemůže obsahovat žádná pole, jen tím říkáš, jaké funkce/vlastnosti musí objekt mít.
Vylučuje se to snad s tím, co jsem napsal? Datová pole jsou součástí implementace.
U her se většinou generalizuje, příklady že máš třídu Truhla jsou jen z učebnic objektově orientovaného programování. Co konkrétně děláš?
No právě, dokud se nepodívá do zdrojáku, tak netuším, jestli je List třída nebo Interface. Když jsou tam názvy končící -able a podobně, tak se to ještě dá, ale interface List mi přijde velmi zavádějící a jediná možnost jak kód pochopit je lovit v manuálu.
Ale pořád mi z toho nedochází, proč bych měl vědět, zda je List třída nebo interface. Použití je skoro stejné. Dokonce z interface mohu klidně udělat instanci anonymní třídy úplně stejně jako ze standardní třídy.
Proto si myslím, že je v principu zbytečné ty názvy rozlišovat nějakým "I" na začátku názvu. Je to jen nějaká konvence specifická pro C#, PHP a možná pár dalších jazyků, ale Java ji nepotřebuje.
Hodi se to vedet - treba tohle udelat (v C#) nemuzes:
ISerializable data = new ISerializable();
Bez toho rozdilneho pojmenovani to nepoznas, musis se divat do manualu.
Ale uz muzes samozrejme udelat:
ISerializable data = new TridaImplementujiciISerializable();
(to jsi tu popisoval)
Jak je to u jinych jazyku nevim, ale treba v C# nemuzes vytvorit instanci interfacu.
V Javě můžeš instanci z interface vytvořit například takto:
interface Command {
void execute();
}
public class Comm {
public static void main(String[] args) {
Command hello = new Command() {
public void execute() {
System.out.print("Hello ");
}
};
Command world = new Command() {
public void execute() {
System.out.print("World! ");
}
};
hello.execute();
world.execute();
}
}
Dokonce v tomto případě interface může být i uvnitř třídy Comm.
Tak jasně že nebudu mít třídu Truhla ale spíše třídu, která bude rozšířená o to že bude dělat větší interakci s hráčem. Otevře se, nabíde svůj seznam položek, které vlastní apod.
Co přesně dělám ? Je to závěreční práce z programování 2.ročníku. Je to hlavně spíše návrh trochu "univarzálnějšího enginu", tedy snažím se to psát tak aby se to dalo alepoň zčásti použít i jinde.
Ten test (hra) bude vlastně 2D hra z ptačí perspektivy, kde budeš chodit náhodně vygenerovaným bludištěm s místnostimi, hledat poklady a sem tam porazíš potvoru.
Hlavně zde zkouším kameru, světl. Časem chci zkusit různé efekty, implementovat nějakou pěknou AI, prostě vytvořit něco co bude ukázkou jak to všechno pracuje. Uvidím jak to vše budu stíhat. Učiteli bude stačit když se budu moct procházet, střílet a aby tam byla nějaká lehčí AI. Světlo je navíc a ono vlastně funguje, jenom je to prostě špatně navržené a trochu se to zkomplikovalo. Proto jsem si řekl, že to opravím dřív než později.
Byla by tam nějaká třída Kontejner, která by měla vlastnosti jako název, sprite a podobně. Hráč by její instanci jednou viděl jako truhlu, jednou jako popelnici a podobně. Rozhraní má smysl v případě, když bys tam chtěl třeba objekt, co je zároveň jako kontejner a zároveň jako vozidlo (třeba auto má kufr pro přepravu věcí a jde s ním i jezdit), potom by třída auto implementovala rozhraní IVozidlo i IKontejner. Výhoda rozhraní je, že uděláš jednou práci s kontejnerem a pak ti je šumák jestli je to krabička od zápalek nebo náklaďák, vidíš jen tu část objektu, kterou v danou chvíli potřebuješ.
Hm, zajimave, ani netusim, jestli v c# neco podobneho jde, ale v podstate je to jen anonymni trida implementujici to rozhrani, takze to neni doopravdy instance rozhrani, ne?
Však tak to myslím A s
tím rozhraním. Asi ho tedy použiju pro to světlo. Všechny objekty , které
mohou být osvětlené budou implementovat to rozhraní a tím krásně
nastavím světla. No trochu to přepíšu a budu psát dál. Už vím že teď
to nebudu extra dobrý
.
Každopádně až to sepíšu, pošlu sem komplet kód a budu strašně rád,
když se na to někdo z vás mrkne a řekne co je dobrý, co je špatný. Co
udělat líp apod.
Já sice chápu výhodu rozhraní ale stále nevím jak ho správně
používat. Dokud asi neuvidím nějaký složitější příklad, nepochopím
to úplně dobře
Jinak koukám, že jsi asi jediný, co dělá na tom "společném projektu"
No ten "společný projekt" se totálně rozpadl. A stále mám v hlavě svůj nápad. Teď dělám tedy na Alpha v0.000005, která bude mít základy a poslouží i jako závěrečná práce.
Měli jsem 2 schůzky na Skypu, přišel jsem já, Michael Olšavský a Satik.
Jeden Anonym měl pravdu, neumíme se domluvit, organizovat. Nebo aspoň já
nedokážu asi (zatím) úplně organizovat skupinu lidí napříč republiky
Ano, je to vytvoření instance anonymní třídy. Úplně to samé však můžeš udělat s každou nefinální třídou.
Ber to tak, že standardní třída má kromě interface ještě navíc implementaci. Můžeš ji překrýt, ale u interface ji překrýt musíš. Třída, abstraktní třída a interface mají společné vlastnosti. Je tedy možné je rozlišit "I" na začátku, ale nutné to není.
David Hartinger nemel na mysli nazvy vlastnosti zacinajici na I, ale primo nazev
rozhrani zacinajici na I.
U vlastnosti to nema smysl pojmenovavat jinak, protoze to preci kazda trida uz
nejak implementuje.
Neměl jsem na mysli "vlastnosti", ale společnou podmnožinu použitelnosti. Kruci, jak jinak napsat slovo vlastnosti, aby to nebyly gettery a settery.
Zobrazeno 37 zpráv z 37.