Autor | Zpráva | ||
---|---|---|---|
MaK Profil |
#1 · Zasláno: 23. 10. 2013, 11:34:21
Mám dvě třídy A1a A2, které mají obdobné vlastnosti.
To zda bude v celém projektu používat tu či ono třídu řeším pomocí: if (COSI) class A extends A1{}; else class A extends A2{}; A pak všude používám jen třídu A. Potud všechno funguje. Ale třída A1 vyhazuje vyjímku A1Exception a třída A2 vyhazuje A2Exception. Pokud to napíšu obdobně: if (COSI) class AException extends A1Exception{}; else class AException extends A2Exception{}; tak to nejde, neboť AException nezachyti svého předka. Co teď? MaK |
||
juriad Profil |
#2 · Zasláno: 23. 10. 2013, 11:43:07
Brzdi, to co prováďíš bys nikdy provádět neměl. Existuje lepší řešení, které nezneužívá dědičnost.
|
||
MaK Profil |
#3 · Zasláno: 23. 10. 2013, 11:52:08
juriad:
A jaké je to lepší řešení? |
||
juriad Profil |
Měl bys mít třídu A; a pak třídy A1 a A2, které od A dědí (tedy přesně naopak).
Znát třídu A1 nebo A2 musíš jen v okamžiku, kdy vytváříš instanci (na to můžeš mít statickou metodu). Všude jinde ti stačí vědět, že pracuješ obecně s nějakým potomkem třídy A: abstract class A { public static function create() { if (COSI) { return new A1(); } else { return new A2(); } } } class A1 extends A {} class A2 extends A {} Maximum kódu jistě můžeš implementovat obecně (jen jednou) ve třídě A. |
||
MaK Profil |
#5 · Zasláno: 23. 10. 2013, 12:22:12
juriad:
třídu A1 jsem dělal já, třídu A2 někdo jiný. Těžko se shodneme na společném předkovi. |
||
Tori Profil |
#6 · Zasláno: 23. 10. 2013, 13:00:56
MaK:
„Těžko se shodneme na společném předkovi“ Jak potom můžete ty třídy používat, když třeba mají jiné názvy metod, jiné signatury? To máte ještě na víc místech v kódu tu podmínku if (něco) $instanceA1->něco(); else $instanceA2->něcoJiného($param); ?
|
||
juriad Profil |
#7 · Zasláno: 23. 10. 2013, 14:02:58
MaK:
Ale obě třídy (A1, A2) musí mít minimálně stejné metody. Takže stačí do A1 a A2 přidat extends A ; a v A definovat abstraktní metody. Časem se prostě v třídách A1 a A2 udělá pořádek.
|
||
MaK Profil |
#8 · Zasláno: 23. 10. 2013, 14:25:44
juriad:
Ano maji stejne metody, promenne i konstanty. Alespon ty, ktere pouziva projekt. Co když cizí třída už nějakého předka má? Co když je to třída, která je součástí PHP? Něco jiného by nebylo? Něco jako preprocesor z C: // A bude nahrazeno A1 #define A A1 |
||
juriad Profil |
#9 · Zasláno: 23. 10. 2013, 14:34:39
Nemusí to být dědičnost (zmínil jsem ji z důvodu, že už ji používáš a že je dost pravděpodpbné, že se v A1 a A2 budou opakovat některé metody). Můžeš použít rozhraní (http://php.net/manual/en/language.oop5.interfaces.php); třída může implementovat několik rozhraní. V tom rozhraní budou jen hlavičky funkcí.
|
||
Tori Profil |
#10 · Zasláno: 23. 10. 2013, 14:51:03
Pokud jsou A1 i A2 interní třídy PHP a jde vám jen o to, že nevíte, která bude kde dostupná, tak je můžete schovat za adaptér + 2 drivery. Tak budete mít jednu třídu s jediným rozhraním/signaturou + jedinou výjimku. Uvnitř adaptéru bude soukromá proměnná s instancí toho kterého driveru. Vizte např. strukturu dibi.
|
||
Joker Profil |
#11 · Zasláno: 23. 10. 2013, 15:03:35
juriad:
„Takže stačí do A1 a A2 přidat extends A ;“
Pokud to je cizí třída, nepřipadá mi to moc vhodné. Můžu taky používat nějaký balíček tříd spravovaný někým jiným a pak je dost nepraktické si v něm dělat svoje úpravy do každé verze na kterou aktualizuji. MaK „třídu A1 jsem dělal já, třídu A2 někdo jiný. Těžko se shodneme na společném předkovi.“ No a proč nemůže A1 být potomkem A2? To mi připadá jako logická cesta, když mám cizí třídu a chci ji přepsat: Podědím ji a pak si přepíšu to co potřebuji. |
||
MaK Profil |
#12 · Zasláno: 23. 10. 2013, 15:34:04
Tori:
Jestli tomu dobře rozumím, napsal bych adapter, ktery by kopíroval metody,konstanty, PROMENNE!? obou tříd a v každé metodě měl jeden řádek: return $service->metoda(....); A ještě drivery? To je něco co obalí současné A1 a A2? Nebo to jsou již A1 a A2. |
||
Tori Profil |
No, vlastně vzoru Adapter spíš odpovídají ty "drivery". Sloužily by k tomu, aby se srovnaly rozdíly mezi A1 a A2, pokud tam nějaké jsou.
Třeba u té DB vrstvy máte drivery pro MySQL / MySQLi / MSSQL / ..., které zakrývají jejich vzájemné odlišnosti a dodržují nějaké společné rozhraní, třeba IDbDriver . Nadřízená třída Db potom používá jen $this->db->query("...") a nemusí se starat o to, jestli se k databázi připojila přes Mysql/Mysqli/jiné rozhraní, protože $this->db má vždycky stejné rozhraní.
Ale možná to není potřeba. Nepochopila jsem úplně, které třídy můžete změnit a které ne. |
||
MaK Profil |
#14 · Zasláno: 23. 10. 2013, 16:41:32
Díval jsem se jak to dělá DIBI. Ano, pokud mám dostatek času, nebo jsem autorem něčeho jako je DIBI, pak mohu puvodní třídy obalit drivery. Nad ti postavit adaptér a na konci dne si řeknu: "To jsem si pěkně zaprogramoval." :)
Díky všem za snahu. |
||
Časová prodleva: 10 let
|
0