Classes maken
Ik ben nu al een tijdje bezig met me te verdiepen in OOP en Classes maken e.d.
Ik heb al menig tutorial bekeken en ook al wat werkends in elkaar gezet.
Maar ik begrijp niet goed wanneer je nu een class maakt of een class extend.
Even een voorbeeld:
Ik heb de volgende objecten:
- Artikelen (in dit geval een product)
- Onderdelen (artikel bestaat uit 1 of meer onderdelen)
- Materialen (onderdeel bestaat uit een bepaald materiaal van een bepaalde lengte)
- Bewerkingen (aan een onderdeel moeten 1 of meerdere bewerkingen worden gedaan)
- Pakbonnen (in een pakbon zitten 1 of meerdere artikelen)
- Facturen (in een factuur zitten 1 of meerdere pakbonnen)
Ik heb nog wel meerdere objecten maar laten we het hier even bij laten.
Even voor mijn beeldvorming: Is het nu de bedoeling dat ik van de bovenstaande objecten aparte classes maak? Of is het beter om bijvoorbeeld te zeggen dat onderdeel een child (extend) is van artikel?
Kan mij iemand een aanzetje geven?
Alvast bedankt.
Gewijzigd op 20/02/2015 22:25:17 door Johan Rombouts
Er zijn in OO 2 relaties die je goed moet onthouden:
* IS_EEN
* HEEFT_EEN
Bij bijv. een webshop van een boekenwinkel kun je zeggen "een Boek IS_EEN Artikel". Je kan ook zeggen "een Boekenwinkel HEEFT_EEN Boek" (meerdere boeken, maar ten minste 1 boek). Je kunt niet zeggen "Een Boekenwinkel IS_EEN Boek" of "een Boek HEEFT_EEN Artikel" (tenzij je Artikel een andere betekenis geeft).
De IS_EEN relatie is degene waar je extend gaat gebruiken. Dus:
Code (php)
De HEEFT_EEN relatie duid een property aan die een andere class bevat:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
class BoekenWinkel
{
private $boeken = array();
public function heeftBoek(Boek $boek)
{
$this->boeken[] = $boek;
}
}
$hetWinkeltjeOpDeHoek = new BoekenWinkel();
$hetWinkeltjeOpDeHoek->heeftBoek(new Boek('Head First Design Patterns'));
$hetWinkeltjeOpDeHoek->heeftBoek(new Boek('Zomerhuis met Zwembad'));
?>
class BoekenWinkel
{
private $boeken = array();
public function heeftBoek(Boek $boek)
{
$this->boeken[] = $boek;
}
}
$hetWinkeltjeOpDeHoek = new BoekenWinkel();
$hetWinkeltjeOpDeHoek->heeftBoek(new Boek('Head First Design Patterns'));
$hetWinkeltjeOpDeHoek->heeftBoek(new Boek('Zomerhuis met Zwembad'));
?>
De meest gebruikte fout is het teveel gebruiken van extend. In heel veel gevallen kun je extend vervangen door een andere oplossing, die vaak veel flexibeler en correct is dan een extend. Je zou bijv. kunnen zeggen "een Admin IS_EEN User", maar als je echt naar het verschil tussen een Admin en een User kijkt dan zul je zien dat eigenlijk alleen zijn rechten anders zijn. Hetzelfde geld voor "een Moderator IS_EEN User". Daarom zou het in zo'n geval beter zijn om 1 User class te hebben, die een property "rechten" (roles) heeft, waarin staat wat ie mag en niet mag. Of beter, dat de user een groep krijgt en een andere class bepaald of die groep iets wel of niet mag.
Als je een class schrijft die een andere class extend neem je in eerste instantie alle functionaliteiten over van de onderliggende class.
Code (php)
class B heeft nu EXACT dezelfde functionaliteit als class A.
Nu kunnen we deze gaan veranderen door methods (functies) te gaan overschrijven of door methods of properties (variabelen) er aan toe te voegen. We kunnen dus een 'uitgebreidere' versie van class A gaan maken:
Code (php)
Vanaf nu heeft class B twee methods:
- sayHello() en
- sayBye()
Maar wanneer gebruik je dit nou? Eigenlijk alleen maar als je praat over soorten.
Ik kan zelf maar een paar voorbeeldjes noemen waarvan ik er hier één noem:
De validator
Als we een formulier maken en de gebruiker kan een aantal velden invullen dan willen we deze velden vaak valideren. Bijvoorbeeld als er een veld 'mailadres' in het formulier is dan willen we controleren of de ingevulde tekst wel voldoet aan een geldig mailadres. Een ander voorbeeld is een veld 'aantal'. Hier verwachten we uitsluitend een numerieke waarde. Hierop willen we dit veld tevens controleren (of valideren).
Zo zou je dan een basismodel validator kunnen maken. We noemen dit dan ook wel de baseclass. Daarnaast zou je van alle soorten validators een class kunnen aanmaken die de standaard functionaliteit van de baseclass overneemt door deze te extend-en:
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
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
<?php
class Validator
{
public function validate($content)
{
return TRUE;
}
}
class EmailValidator extends Validator
{
// overschrijf de functie validate van de baseclass 'Validator'
public function validate($content)
{
return filter_var($content, FILTER_VALIDATE_EMAIL);
}
}
class NumericValidator extends Validator
{
// overschrijf de functie validate van de baseclass 'Validator'
public function validate($content)
{
return is_numeric($content);
}
}
?>
class Validator
{
public function validate($content)
{
return TRUE;
}
}
class EmailValidator extends Validator
{
// overschrijf de functie validate van de baseclass 'Validator'
public function validate($content)
{
return filter_var($content, FILTER_VALIDATE_EMAIL);
}
}
class NumericValidator extends Validator
{
// overschrijf de functie validate van de baseclass 'Validator'
public function validate($content)
{
return is_numeric($content);
}
}
?>
In alle andere gevallen kun je beter de HEEFT-EEN gebruiken waar Wouter al over schreef. Voorbeeld:
Een klant heeft een postadres maar ook een afleveradres
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
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
<?php
class Address
{
private $street;
private $postcode;
private $city;
public function setAddress($street, $postcode, $city)
{
$this->street = $street;
$this->postcode = $postcode;
$this->city = $city;
}
}
class Customer
{
private $postaddress;
private $deliveraddress;
public function setPostaddress(Address $address)
{
$this->postaddress = $address;
}
public function setDeliveraddress(Address $address)
{
$this->deliveraddress = $address;
}
}
?>
class Address
{
private $street;
private $postcode;
private $city;
public function setAddress($street, $postcode, $city)
{
$this->street = $street;
$this->postcode = $postcode;
$this->city = $city;
}
}
class Customer
{
private $postaddress;
private $deliveraddress;
public function setPostaddress(Address $address)
{
$this->postaddress = $address;
}
public function setDeliveraddress(Address $address)
{
$this->deliveraddress = $address;
}
}
?>
Gewijzigd op 21/02/2015 01:01:32 door Frank Nietbelangrijk