Class versus functie
Ik probeer uit te vinden wanneer je nou beter een class kunt gebruiken dan een functie.
Ik heb inmiddels een aantal filmpjes bekeken en tutorials gelezen, ook die op deze site, maar die gebruiken allemaal een soort real life-voorbeelden die ik niet kan omdenken in php-voorbeelden. Een kleur is een eigenschap van een oog wat weer hoort bij een mens. Dat klopt allemaal, maar het legt niet uit waarom en vooral: IN WELK GEVAL ik een class moet gebruiken ipv een (stel) functie(s).
Kan iemand een simpel, maar wel *echt* voorbeeld noemen waarbij je ook kan uitleggen waarom het beter is dan het gebruik van functies?
Ik heb zo het gevoel dat al die tutorialschrijvers ( aan wie ik zoveel php-kennis dank!) het concept zelf al beheersen (ja, duh) en dat het een lastig iets is om dan nog het precieze verschil uit te leggen...
Ik denk dat je vooral wilt weten wat OOP is. Vroeger werd alles "achter elkaar" geprogrammeerd en voor dingen die vaker voorkwamen werden functies geschreven. OOP is een andere benaderings/zienswijze van programmeren. Nu kan ik daar wel iets over vertellen, maar ik denk dat je beter een tutorial hierover kan lezen.
Je zou hier http://phptuts.nl/view/45/ eens de eerste 4 hoofdstukken/pagina's kunnen doorlezen. Hopelijk helpt dat al wat. Als je daarna vragen hebt, stel ze gerust.
Ik snap ook wel dat stukje over dat in oop alles war je programmeert niet meer moet zijn dan 1 object. En dat je de code steeds opnieuw kunt gebruiken.
Het voorbeeld echter in hs 4 met die usernames jan en Inge, daar is het nut me volstrekt duister van. Dat bedoelde ik met dat ik dat voorbeeld niet kan omdenken in een *echt* voorbeeld dat je op deze manier zou maken
Oké, kun je dan iets specifieker zijn? Waar zie je het nut niet van in? Wat is hetgeen wat jij vreemd vindt?
Kijk in een zeer simpel en kort PHP script is deze behoefte er inderdaad niet. Wanneer een script of liever dan een heel pakket groter wordt dan wordt de code-brei al snel erg onoverzichtelijk. Daarbij loop je tevens al snel tegen problemen aan zoals bijvoorbeeld:
Heeft de functie validate nou betrekking tot het valideren van een formulier, of misschien wel een datum, of een wachtwoord? Al snel wil het voorkomen dat dat er twee functies Validate() in het systeem voorkomen hetgeen een foutmelding oplevert. Kort gezegd is het een probleem om zonder goede structuur grote projecten te ontwikkelen. Je zou deze projecten eigenlijk moeten onderverdelen in kleinere projecten zodat ze overzichtelijk blijven. Dat is nou precies wat je met classes doet, Je gaat je code onderverdelen in kleinere complete stukken.
Is dat het? nee. de classes zijn ook zo ontworpen dat je ze heel makkelijk kunt gebruiken zonder dat je de code hoeft te begrijpen. Vergelijk dit met een auto. Je hoeft niet zelf een auto te kunnen bouwen of te kunnen onderhouden/repareren om er in te kunnen rijden. Een beetje inzicht in hoe een auto werkt is wel makkelijk natuurlijk maar je wordt van alle gemakken voorzien en in principe wijst het al voor zich.
(hier komt al een beetje de OOP gedachte om de hoek want een auto is gewoon een object die je als mens kunt gebruiken).
declareren en instantiëren.
Zoals je waarschijnlijk al weet zal je elke functie die je schrijft voor en spek en bonen schrijven als je hem nergens in je code aanroept. Het schrijven van de functie noemen we declareren. de functie is eigenlijk een soort blauwdruk/ontwerp maar als je eenmaal een functie hebt geschreven kun je hem zo vaak gebruiken als je nodig acht. Bij classes is dat ook zo maar gaat er nog een stapje verder in. Classes ga je natuurlijk ook schrijven of zoals je wilt declareren. Daarna moet je ze echter nog instantiëren. dat doe je met het keyword 'new'. je maakt op dat moment een nieuw object aan in het geheugen. Het mooie er van is dat je niet alleen
een object van dezelfde class in het geheugen kunt hebben maar meerdere.
stel je hebt een class:
je kunt dan bijvoorbeeld meerdere verschillende objecten van deze class in het geheugen aanmaken:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
$red = new Color;
$red->color = #FF0000¨;
$green = new Color;
$green->color = #00FF00¨;
?>
$red = new Color;
$red->color = #FF0000¨;
$green = new Color;
$green->color = #00FF00¨;
?>
Je hebt nu twee instanties van de class Color in het geheugen. Deze gebruiken dezelfde functies en variabelen maar de variabelen hebben alleen andere waarden. Je kunt de instanties benaderen door de variabele te gebruiken die we aangemaakt hebben voor het woordje ´new´ gevolgd door een ->. je kunt de instanties willekeurig door elkaar gebruiken.
inkapseling (encapsulation)
Met classes ga je functies en variabelen bij elkaar inkapselen (lees bij elkaar houden) en zelfs bepalen welke functies en variabelen publiekelijk toegankelijk zijn en welke privé zijn. Bij publiek kunnen ze van buiten het object aangeroepen worden maar bij privé niet. Privé functies of variabelen zijn zodoende altijd functies die door andere (publieke) functies van dezelfde class worden gebruikt. Het inkapselen geeft een veel betere en leesbaardere structuur aan de code.
properties en methods
Waar we normaal altijd over variabelen en functies praten noemt men deze bij classes properties en methods
1) functie of class gebruiken
2) OOP of procedureel programmeren
Een class gebruiken wil namelijk niet direct zeggen dat je je hele applicatie als een OOP applicatie ontwerpt (zoals door iemand boven mij wordt gesuggereerd). Je kan prima binnen een procedureel gebouwde applicatie een class gebruiken. In dat geval zal je de keuze voornamelijk moeten maken vanwege het bij elkaar houden van data en functionaliteit. Neem een database connectie. Overal waar je in je code een query moet uitvoeren heb je een paar zaken nodig:
1) database connectie
2) functie om de query uit te voeren
3) foutafhandeling
Dit kan je overal in je code opnieuw schrijven, maar moet je dan over van mysql naar mysqli, dan zit je al met een probleem. Het uitvoeren van de query inclusief de foutafhandeling wil je dus op 1 plek hebben en niet meer. Daarnaast heb je continu die connectie nodig, die je verder nergens nodig hebt. Wat als dat nu al vast in die functie zou zitten. Dan hoef je er ook verder nergens over na te denken. Dat is een praktisch voorbeeld waar een class erg handig zou zijn. Je maakt 1 keer een class aan in je code, die class beheert de connectie naar de database, voert queries uit en kan de fouten afhandelen. Alles op 1 plaats en als er iets mis gaat hoef je alleen die ene class aan te passen.
Ga je nu nog een stap verder, dan ga je je hele applicatie in OOP ontwikkelen. Dan heb je het eigenlijk ook niet meer over classes, maar over objecten. Dan ga je alle functionaliteit in je applicatie splitsen in objecten waarbij elk object de verantwoordelijkheid krijgt voor 1 bepaalde functionaliteit. Bovenstaand voorbeeld voor een database class zal je dan waarschijnlijk ook nog eens splitsen in 3 objecten.
Het grote voordeel van OOP versus procedureel is het gemak van onderhoud en de uitwisselbaarheid. In het begin kost het veel meer werk om het op te zetten, maar uiteindelijk zal je veel tijd winnen doordat je nooit twee keer hetzelfde hoeft te doen. Zelf niet tussen meerdere applicaties.
Merk overigens ook op dat je binnen classes geen functies hebt, maar methodes. In php staat er weliswaar het keyword function voor, maar er zit een wezenlijk verschil tussen.
@Ozzie: Wat ik 'duister' vind aan dat voorbeeld is dat je in een script dat als doel heeft de output van twee namen je dat niet met een class doet - denk ik dan.
Ik snap wel dat het zo kan, maar het lijkt me niet echt heel nuttig en daarom kan ik aan zo'n voorbeeld niet het voordeel van classes tov functies - of eigenlijk, zoals ik inmiddels geleerd heb OOP vs procedureel programmeren - aflezen.
Voorbeeld: ik ben voor mijn leerlingen (maar eigenlijk vooral in eerste instantie voor mn eigen lol) begonnen met een script om sommen uit te kunnen rekenen: je krijgt een som, je tikt het antwoord in een vakje en dan verzend je dat.
Ik heb als beginnetje iets gemaakt dat
- moeilijke tafelsommen opgeeft, alleen sommen die een antwoord boven de 30 hebben
- alle komen maar één keer voor
- als alle mogelijkheden geweest zijn stopt het script automatisch
Ik wil het graag uitbreiden met:
- je kunt ook kiezen voor plus-, min- en deelsommen
- je kunt instellen wat de range is waarbinnen de cijfers liggen die je verrekent, of
- je kunt instellen binnen welke range de antwoorden vallen
- het programma slaat op
- het aantal gemaakte sommen
- het aantal goede
- het aantal foute
- de foute sommen zelf
Zoiets.
Op welke manier zou je hier OOP inzetten?
Zou dan het deel van de code dat de sommen uitrekent één class worden? Of vier, het aantal operatoren dat gebruikt wordt?
Ik zie bijvoorbeeld niet waar of hoe ik hier instances nodig zou hebben...
Tsja. Vragen, vragen....
Aha, het doel is ook niet die 2 namen ;)
Denk eerder (versimpeld) aan zoiets:
Code (php)
Je maakt dus een User object, en dat object vertegenwoordigt een gebruiker. Bijvoorbeeld jou. Vervolgens kun je aan dat object allerlei informatie vragen, waardoor dat object als het ware een echte persoon wordt. Dat object wordt dus niet enkel aangemaakt om een naam op te vragen zoals je ziet.
Dat bedoel ik dus. Waarom nou een class en niet een simpele functie...
Kan dat? Waar haalt die functie dan zijn data vandaan?
Erwin H op 08/05/2014 10:09:39:
Merk als eerste op dat je twee keuzes moet maken:
1) functie of class gebruiken
2) OOP of procedureel programmeren
1) functie of class gebruiken
2) OOP of procedureel programmeren
Aangezien de TS nog niet veel ervaring heeft met het gebruik van classes wil ik voorstellen het hele OOP verhaal nog achterwege te laten.
Lijkt mij persoonlijk niet. Beter ineens goed leren.
Maar goed, ik wil het inderdaad graag leren.
Wil je eens naar mijn voorbeeld kijken (sommen) om aan te geven hoe je daar OOP/Classes zou gebruiken?
En dan hou 'k op met zeuren ;-)
TS => topic starter... jij dus ;)
Duud'luk.
Dh boor op 08/05/2014 21:17:23:
Maar goed, ik wil het inderdaad graag leren.
Waar een wil is is een weg :)
Toevoeging op 09/05/2014 00:54:08:
Erwin H op 08/05/2014 17:31:32:
Kan dat? Waar haalt die functie dan zijn data vandaan?
@dh Boor: Snap je nu wat Erwin hiermee bedoelt?
een class is een afgeschermd stukje code met zijn eigen data. Die data hoort bij die class en zal niet zomaar even overschreven worden door een heel ander deel uit de applicatie.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
// hieronder wordt een variabele gedeclareerd in de global space.
// deze variabele blijft gedurende het gehele script in het geheugen
$a = 5;
function test()
{
$a = 10; // deze variabele wordt weer 'vergeten' nadat de functie doorlopen is.
}
echo $a . '<br>';
class User
{
// properties
/* deze properties bestaan zolang de instantie van de class bestaat!
Bovendien kunnen deze variabelen door alle functies binnen de class gelezen of veranderd worden.
Om de properties te benaderen maken we gebruik van $this->
*/
private $voornaam;
private $achternaam;
private $email;
// methods
public function setVoornaam($voornaam)
{
$this->voornaam = ucfirst($voornaam);
}
public function setAchternaam($achternaam)
{
$this->achternaam = ucfirst($achternaam);
}
public function getVolledigeNaam()
{
return $this->voornaam . ' ' . $this->achternaam;
}
}
$a = new User(); //
$a->setVoornaam('dh');
$a->setAchternaam('Boor');
$b = new User();
$b->setVoornaam('Frank');
$b->setAchternaam('Niet Belangrijk');
echo $a->getVolledigeNaam() . '<br>';
echo $b->getVolledigeNaam() . '<br>';
?>
// hieronder wordt een variabele gedeclareerd in de global space.
// deze variabele blijft gedurende het gehele script in het geheugen
$a = 5;
function test()
{
$a = 10; // deze variabele wordt weer 'vergeten' nadat de functie doorlopen is.
}
echo $a . '<br>';
class User
{
// properties
/* deze properties bestaan zolang de instantie van de class bestaat!
Bovendien kunnen deze variabelen door alle functies binnen de class gelezen of veranderd worden.
Om de properties te benaderen maken we gebruik van $this->
*/
private $voornaam;
private $achternaam;
private $email;
// methods
public function setVoornaam($voornaam)
{
$this->voornaam = ucfirst($voornaam);
}
public function setAchternaam($achternaam)
{
$this->achternaam = ucfirst($achternaam);
}
public function getVolledigeNaam()
{
return $this->voornaam . ' ' . $this->achternaam;
}
}
$a = new User(); //
$a->setVoornaam('dh');
$a->setAchternaam('Boor');
$b = new User();
$b->setVoornaam('Frank');
$b->setAchternaam('Niet Belangrijk');
echo $a->getVolledigeNaam() . '<br>';
echo $b->getVolledigeNaam() . '<br>';
?>
Gewijzigd op 09/05/2014 00:59:26 door Frank Nietbelangrijk