Door
Ozzie PHP
op 19-06-2014 23:42
gewijzigd op 19-06-2014 23:43
4.065 views
Ola,
Een vraag. Ik heb 3 classes die dezelfde abstracte class extenden.
Nu heb ik een verplcihte method foo(). Bij 2 van deze classes is de invulling van die method foo() precies hetzelfde. Bij de 3e class zit er een verschil in.
Wat is nu gebruikelijker?
optie 1)
We bouwen de overkoepelende foo() method van class 1 en 2 als abstracte method in de abstracte class. Class 1 en 2 gebruiken dus de foo() method uit de abstracte class. Class 3 krijgt z'n eigen foo() method.
optie 2)
In de abstracte class declareren we een lege abstracte foo() method en iedere class vult zelf deze method in. In class 1 en 2 is deze method exact hetzelfde.
je gebruikt die abstractie wanneer je weet dat ELKE klas die het overneemt de zelfde implementatie gebruikt van die methode. wanneer je dit dus verschillend hebt dan kan je het beter leeg laten. Overigens is het beter te programmeren naar een interface dan naar een implementatie.
Oké... maar dat ben ik niet helemaal met je eens. Een op zichzelf staande interface (het 2e dus) gebruik je met name om naar bepaald "gedrag" te programmeren. Je kunt er mee aangeven dat een object zich op een bepaalde manier gedraagt (met de daarbij behorende methods). Een abstracte class is óók een interface, maar beschrijft een kant-en-klaar object.
Naar mijn mening zijn abstracte klasses alleen goed wanneer je kan zeggen
een mercedes IS_EEN auto
een volvo IS_EEN auto
voor al het andere raad ik de interface aan. Waarom is de abstracte klasse niet altijd optimaal? Je kan het maar weinig gebruiken ( alleen in een IS_EEN relatie ) en verder is de code al geïmplementeerd waardoor je niet flexibel kan zijn met je implementatie.
p.s. overigens zijn jou voorbeeldjes vaag altijd waardoor je niet echt een tegenargument kan geven want wat is een foo? ^^
>> p.s. overigens zijn jou voorbeeldjes vaag altijd waardoor je niet echt een tegenargument kan geven want wat is een foo? ^^
Hehe... lol. Het maakt in dit geval niet uit wat foo is omdat de vraag daar niet over ging :)
In dit geval gaat het inderdaad om een IS_EEN relatie, dus dat klopt. Het ging me alleen dus even om hoe ik moet omgaan met een method die meerdere keren voorkomt maar niet overal. Maar daar had je me al antwoord op gegeven. Ik maak er dus een lege abstracte method van, en dan zal ik dus moeten accepteren dat die method in 2 classes op precies dezelfde manier wordt ingevuld.
Programmeren naar een interface doelt niet zozeer op het werkelijk gebruiken van een interface. Het doelt er meer op dat je niet moet programmeren naar 1 specifieke implementatie, maar liever het globaler aan moet pakken. Of dat globale nou een andere overkoepelende klasse is, een abstracte klasse of een interface maakt niet zo heel veel uit.
Overigens zou ik deze regel zeker niet altijd aan raden. Heb je bijv. een Factory klasse, dan is het programmeren naar een interface vrij zinloos.
Jouw voorbeeldje met mercedes en volvo zou ik overigens niet met inheritance oplossen (een van de meest misbruikte use cases van inheritance), maar met composition (bijv. het Strategy pattern).
Om op Ozzie's vraag goed te antwoorden hebben we eigenlijk meer context nodig. We zouden in dit geval namelijk voor 3 dingen kunnen kiezen: (1) inheritance, (2) composition of (3) copy/past. Voor alle 3 is wat te zeggen en alle 3 zijn ze juist, in hun eigen context. Welke er hier opgaat is dus volledig afhankelijk van die context.
Wouter, het gaat in dit geval om verschillende autoloaders. Die extenden een abstracte basis-class. Bij sommige autoloaders wil ik bij het toevoegen van de namespace een slash achter de namespace plakken (om ze naderhand op de juiste manier met de fqcn te kunnen vergelijken). Dit is echter niet bij alle autoloader classes nodig. En om die reden verschilt de add_namespace method dus. Bij 2 clases is die hetzelfde, bij 1 class moet die slash worden toegevoegd. Maar wie weet komen er ooit autoloaders bij waarbij ook die slash moet worden toegevoegd. Ik denk dus dat het antwoord van Reshad wel correct is om de invulling per class te regelen.
Toevoeging op 20/06/2014 00:28:09:
P.S.
>> Ook interfaces moeten een IS_EEN relatie hebben.
Als je een "op zichzelf staande" interface bedoelt is dit niet helemaal waar.
Je kunt bijv. een interface Drivable hebben, die geimplementeerd wordt door een Car en een Bike class. Zowel een Car als een Bike !IS_EEN Drivable. Drivable beschrijft GEDRAG wat in de implementerende classes voorkomt.
>> Bij sommige autoloaders wil ik bij het toevoegen van de namespace een slash achter de namespace plakken (om ze naderhand op de juiste manier met de fqcn te kunnen vergelijken).
Een slash achter een namespace?
<?php
namespace DontTryThisAtHomeFolks/;
?>
Of een backslash?
<?php
namespace MoreFooLishNess\;
?>
Die slash of backslash hoort er niet in. Oplossing (4) weg ermee.