Ik heb een vraagje en wellicht kan iemand mij een duwtje in de goede richting geven.
Hoe moet je precies een interface gebruiken?
Maak je een interface op method niveau, of op class niveau?
Is het bijvoorbeeld de bedoeling dat je een datacollectionInterface maakt, met als methods get() en set(). Of is het de bedoeling dat je een getInterface en een setInterface, en dan eventueel een getSetInterface die die 2 andere interfaces extend?
Ik wil vooral de achterliggende gedachte van een interface proberen te begrijpen. Ik hoop dat iemand dat op een simpele manier kan uitleggen, want ik ben een beetje bang dat ik het anders verkeerd aanpak, om er vervolgens over een paar weken achter te komen dat ik alles opnieuw kan doen.
Kan iemand me een beetje wegwijs maken? Hoeft echt geen lang verhaal te zijn, maar met name hoe ik mijn interfaces het beste kan opbouwen. Even een zetje in de goede richting zeg maar. Alvast bedankt.
*Interface
Wat betekent bv. CarInterface, niet *able.
En dos, we hebben het hier uiteraard over PHP en niet over een andere taal.
Carable is ook geen goed engels woord...
Ozzie, het punt dat ik probeerde te maken was dat omdat iets kan (GetInterface, HasInterface en SetInterface opsplitsen) het geen goed idee hoeft te zijn.
In het voorbeeld ben ik uitgegaan van een "ik plits ze op omdat het kan" aanpak en ben daarna inconsequent te werk gegaan. Wat jammer genoeg nog wel eens voorkomt. Zeker als je met meerdere aan de zelfde code base werkt.
PHP laat je niet toe om methoden te overloaden zoals in bijvoorbeeld Java. In php moet de method signature 100% gelijk zijn. Ook een reden waarom ik een algemene SetInterface in php een vreemd idee vind.
Ik heb je punt begrepen Dos. Alleen ik had nog een andere vraag. Stel dus dat je een setInterface hebt, of misschien wel een dataInterface waarvan de set() method een onderdeel is... stel dat ik dan in een child class een set() method implementeer, maar ik wil dat het 2e argument van een bepaald type is, hoe doe ik dat dan? Als je het voorbeeld in mijn vorige post ziet, dan gaat het mis. Ik wil dus wel zorgen dat de child class een set method heeft, maar in de child class zelf wil ik dan kunnen afdwingen wat voor type het argument moet zijn. Hoe krijg je zoiets voor elkaar?
"Ik wil dus wel zorgen dat de child class een set method heeft, maar in de child class zelf wil ik dan kunnen afdwingen wat voor type het argument moet zijn. Hoe krijg je zoiets voor elkaar?"
Gooi een InvalidArgumentException.
Hmmm, oké. Dat is een optie inderdaad. Maar wel irritant dat je dat dan niet via typehinting kan doen :-s
Toevoeging op 07/03/2014 14:56:57:
Ik kan trouwens toch wel in iedere child class de set method overschrijven? Stel ik heb een data class met een set() method. De data class implement de setInterface. Als ik dan een child heb van de data class, kan die de set method van de data class dan overschrijven?
Een setinterface is geen goed idee, want dan doe je iets anders dan wat interface voor dienen. Een data interface met get() en set() ZOU wel kunnen, maar dan enkel in bepaalde usecases.
Lees aub de tutorial die ik je doorstuurde eens door. Daar ga je veel van leren. Je snapt wat een interface is, maar niet wanneer je het moet gebruiken.
"Oké, inderdaad. Ik snap wat een interface is, maar ik weet inderdaad nog niet wanneer ik het moet gebruiken."
Je moet niets. Maar het kan erg handig blijken. Als je programmeert op basis van interfaces in tegenstelling tot implementaties kun je fijn mock classes (http://en.wikipedia.org/wiki/Mock_object) gebruiken om unit tests te schrijven.
"Kunnen jullie mij dan eens uitleggen waarom een setInterface geen goed idee is?"
Een interface SetInterface/Setable binnen de global namespace is te vaag naar mijn idee. Binnen een namespace kan het een specifiekere betekenis hebben. Context is belangrijk.
Nogmaals: mijn mening is dat interfaces functionaliteit moet afdwingen. Het moet tot een zekere hoogte duidelijk worden wat die functionaliteit is. Met jouw SetInterface het het mij niet bepaald duidelijk wat de mogelijke gevolgen zijn van het setten, of wat het voor nut kan hebben.
Vergelijk dat met classes als Serializable, Countable en Iterator.
"Oké... maar zolang je de signature volgt dus wel?"
ja.
Interfaces zijn het contract. Het is de enige methode waarmee je kan zeggen: Nu weet je welke methods je mag aanroepen. Stel:
<?php
class ObjectPersistInterface
{
public function persist($object);
}
class ObjectFetchInterface
{
public function find($id);
public function findAll();
public function findAllBy(array $conditions);
public function findOneBy(array $conditions);
}
?>
Als ik nu in een method doe: ObjectFetchInterface $repository Dan weet ik dat ik van dat object de 4 find* methods mag aanroepen, de persist method niet.