[oop] basis- en verplichte methods

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Ozzie PHP

Ozzie PHP

30/04/2013 02:33:13
Quote Anchor link
Ola mensen,

Ik heb een file cacher gemaakt. Nu kan het zijn dat ik ooit ook een database cacher ga maken. Iedere cacher moet een aantal vaste functies hebben (get, save, remove) en ik wil iedere cacher class in- en uit kunnen schakelen. Deze functionaliteit is voor iedere class hetzelfde. Dat deed me denken aan een tip van Wouter dat ik deze overkoepelende functies moet "bundelen" in 1 class. Hoe moet ik dit nu aanpakken?

Schematisch wil ik dus 2 classes:

Een algemene cacher class:
- deze class bevat deze methods: enable() en disable(). Deze methods werken dus ook echt.
- deze class stelt de volgende functies verplicht voor de overervende class: get(), save() en remove(). Deze functies zijn dus niet ingevuld! Er moet alleen worden aangegeven dat ze verplicht zijn.

Een file cacher class:
- deze class bevat de volgende methods: get(), save() en remove(). Hier zijn de methods wel ingevuld.

Hoe doe ik dit nu in goed OOP? Ik hoop dat het een beetje duidelijk is wat ik bedoel.

(Methods hoeven uiteraard niet uitgewerkt te worden, het gaat me alleen even om de juiste opzet.)
Gewijzigd op 30/04/2013 02:36:14 door Ozzie PHP
 
PHP hulp

PHP hulp

08/01/2025 17:20:46
 
Wouter J

Wouter J

30/04/2013 08:58:33
Quote Anchor link
Allereerst snap ik het enabelen niet. Als je een cache methode niet gebruikt dan maak je die klasse toch gewoon niet aan?

En dan je eigenlijke probleem: Als een klasse bepaalde methods invult, maar nog niet alles dan spreken we van een abstracte klasse:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
abstract class AbstractCache
{
    public function enable()
    { ... }


    public function disable()
    { ... }


    public function isEnabled()
    { ... }


    abstract public function get($id);
    abstract public function save($id, $value);
    abstract public function remove($id);
}

?>


Nu kunnen de subklassen deze 3 abstracte methods invullen en de klasse compleet maken.

Nu zou ik altijd nog een stapje verder gaan en een interface er bovenop zetten. Daar komen dan de methods get, save en remove in. Die hoef je dan niet meer abstract te maken in de AbstractCache klasse:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
interface CacheInterface
{
    public function get($id);
    public function save($id, $value);
    public function remove($id);
}


abstract class AbstractCache implements CacheInterface
{
    public function enable()
    { ... }


    public function disable()
    { ... }


    public function isEnabled()
    { ... }
}

?>
 
Ozzie PHP

Ozzie PHP

30/04/2013 09:35:56
Quote Anchor link
Wow... thanks Wouter!!! Precies wat ik bedoelde!

Waarom ik wil enablen en disablen... in principe staat de cacher altijd aan, dus in mijn programma flow ga ik er vanuit dat ie altijd aan staat:

Hebben we cache, haal dan de gegevens uit de cache op.

Maar het zou kunnen dat ik bijv. moet debuggen. Dan is het wel handig om 'm uit te kunnen schakelen, in plaats van dat ik telkens if-jes eromheen moet bouwen.

Zou je als laatste misschien nog even kunnen uitleggen:
- wat die interface bovenop die abstracte class eigenlijk doet?
- hoe ik de file cacher met de abstracte class moet "verbinden". Gaat dat via "extends"?

Thanks a lot!
 
Wouter J

Wouter J

30/04/2013 12:28:09
Quote Anchor link
Ik hoop dat je het cachen via een service container doet? Dan zou ik zorgen dat de cache service in de test omgeving gewoon een dummy cache class is (eentje die dus niks doet). Dan werk je met de kracht van di.

Die interface is voor typehinten in andere klassen. Het is helemaal niet zeker dat elke cacher die abstracte klasse extend, want misschien heb je er wel een paar die die functionaliteit niet nodig heeft.
Ik heb mezelf aangeleerd altijd te typehinten op interfaces.

Een abstracte klasse is gewoon een klasse, dus inderdaad extends. Ik dacht dat je wel wat van abstracte klassen wist?
 
Ozzie PHP

Ozzie PHP

30/04/2013 12:33:09
Quote Anchor link
"Ik hoop dat je het cachen via een service container doet? Dan zou ik zorgen dat de cache service in de test omgeving gewoon een dummy cache class is (eentje die dus niks doet). Dan werk je met de kracht van di."

Ja, via de service container. Ik heb nog geen test-omgeving. Zover ben ik nog niet :)

"Een abstracte klasse is gewoon een klasse, dus inderdaad extends. Ik dacht dat je wel wat van abstracte klassen wist?"

Ik weet ongeveer wel hoe het werkt, maar ik gebruik het (tot op heden) niet vaak. Dus vandaar eigenlijk...

Toevoeging op 30/04/2013 12:56:20:

Ik ben eigenlijk toch wel benieuwd nog naar het wezenlijke verschil tussen het definiëren van abstracte methods in een abstracte class tegenover het gebruik van een interface. In feite komt het op hetzelfde neer, maar als ik het goed begrijp is een interface bedoeld om aan te geven welke methods in een class moeten zitten, maar... dat doe je in een abstracte class ook door abstracte methods aan te maken. Waar zit dan precies het verschil? Wanneer gebruik je wat?
 
Wouter J

Wouter J

30/04/2013 13:25:37
Quote Anchor link
Een interface definieert methods die klassen buiten de klasse zelf gaan gebruiken. Abstracte methods zijn methoden die de klasse zelf gebruikt.
 
Ozzie PHP

Ozzie PHP

30/04/2013 15:09:43
Quote Anchor link
Hoi Wouter,

Voor jou is het ongetwijfeld helemaal duidelijk wat je bedoelt met "Een interface definieert methods die klassen buiten de klasse zelf gaan gebruiken" maar voor mij niet. De methods in de interface moeten toch in de class aanwezig zij die de interface implements?
 
Wouter J

Wouter J

30/04/2013 15:55:52
Quote Anchor link
Sommige methods worden alleen van binnenuit gebruikt bijv:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
abstract class AbstractFileLoader
{
    public function load($filename)
    {

        $fileLocation = $filename.'.'.$this->getExtension();

        // ...
    }
}


class YamlFileLoader extends AbstractFileLoader
{
    public function getExtension()
    {

        return 'yml';
    }
}

?>


Hierin is getExtension echt nodig voor de werken van de abstracte klasse, en het is minder waarschijnlijk dat een klasse dit van buiten zal gaan gebruiken. Daarom zou ik deze als abstract definiëren:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php
abstract class AbstractFileLoader
{
    // ...

    abstract public function getExtension();
}

?>


De method load daar in tegen is juist bedoeld om te gebruiken buiten de klasse, vandaar dat ik deze in de interface zal zetten:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
interface LoaderInterface
{
    public function load($resource_name);
}

?>


Andere klassen, bijv. een RoutingLoader, kunnen nu typehinten op dit interface en zo zijn ze er zeker van dat de load method bestaat.

Sidenote: Mocht er nu een klasse zijn die de getExtension method wilt gebruiken, dan moet hij natuurlijk alsnog typehinten op de abstracte klasse AbstractFileLoader.

Offtopic:
sorry voor mijn korte reactie, code typen op een tablet is ietwat lastig :)
Gewijzigd op 30/04/2013 16:11:21 door Wouter J
 
Ozzie PHP

Ozzie PHP

30/04/2013 16:59:22
Quote Anchor link
Ah okeej. Dus iets wat je in alle classes nodig hebt en van buitenaf moet kunnen aanroepen stop je in een interface? En als je iets alleen nodig hebt in een bepaald type class dan stop je het in een abstracte method. Begrijp ik het zo goed?

Offtopic:

U heeft een tablet aangeschaft?
 
Wouter J

Wouter J

30/04/2013 17:02:54
Quote Anchor link
Jep, je begrijpt het goed. Als je een method van buiten af gaat gebruiken wil je zeker weten dat hij bestaat. Daarom moet je iets bedenken waardoor je het kan typehinten zonder al te specifiek te zijn. Je kan bijv. niet op YamlFileLoader typehinten, omdat je dan de mogelijk tot andere loaders uitsluit (en daarmee OO pijn doet).

Offtopic:
Jup, eindelijk een Microsoft Surface RT :)
 
Ozzie PHP

Ozzie PHP

30/04/2013 17:06:02
Quote Anchor link
Ah oké, thanks... ik moet het even laten bezinken, maar ik zal dan jouw voorbeeld volgen en een abstracte class en interface toepassen.

Offtopic:

Ah, nice!! Bevalt ie een beetje?
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.