OOP Beginnershandleiding (PHP5)
- Inleiding
- Object geörienteerd denken
- Foute denkwijze
- Object georiënteerd programmeren
- Visibility
- Naamgeving
- Constructor __construct()
- Voorbeeld: HTML tabel
- Inheritance
- Voorbeeld: HTML tabel 2 (inheritance)
- Static methods en properties
- Abstract classes en Interfaces
- Magic methods
- Slotwoord en referenties
- Reacties op deze tutorial
Voorbeeld: HTML tabel 2 (inheritance)
In het eerdere voorbeeld van de HTML tabel hebben we gekeken naar de manier waarop dit OO geprogrammeerd wordt. In dit hoofdstuk gaan we een stapje verder en kijken we naar specifieke eigenschappen van de verschillende onderdelen van de tabel. We gaan op zoek naar een manier om cellen (of althans de inhoud daarvan) efficiënt op verschillende manieren te tonen.Voor dit voorbeeld heb ik een aantal kleine wijzigingen doorgevoerd in de eerdere voorbeeld code:
Code
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
56
57
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
56
57
<?php
class Table {
private $_rows;
public function __construct() {
$this->_rows = array();
}
public function append($row) {
$this->_rows[] = $row;
}
public function draw() {
echo '<table border="1">'.PHP_EOL;
foreach($this->_rows as $row) {
$row->draw();
}
echo '</table>'.PHP_EOL;
}
}
class Row {
private $_cells;
public function __construct() {
$this->_cells = array();
}
public function append($cell) {
$this->_cells[] = $cell;
}
public function draw() {
echo '<tr>'.PHP_EOL;
foreach($this->_cells as $cell) {
$cell->draw();
}
echo '</tr>'.PHP_EOL;
}
}
class Cell {
protected $_content;
public function __construct($content) {
$this->_content = $content;
}
public function draw() {
echo '<td>'.$this->_content.'</td>'.PHP_EOL;
}
}
?>
class Table {
private $_rows;
public function __construct() {
$this->_rows = array();
}
public function append($row) {
$this->_rows[] = $row;
}
public function draw() {
echo '<table border="1">'.PHP_EOL;
foreach($this->_rows as $row) {
$row->draw();
}
echo '</table>'.PHP_EOL;
}
}
class Row {
private $_cells;
public function __construct() {
$this->_cells = array();
}
public function append($cell) {
$this->_cells[] = $cell;
}
public function draw() {
echo '<tr>'.PHP_EOL;
foreach($this->_cells as $cell) {
$cell->draw();
}
echo '</tr>'.PHP_EOL;
}
}
class Cell {
protected $_content;
public function __construct($content) {
$this->_content = $content;
}
public function draw() {
echo '<td>'.$this->_content.'</td>'.PHP_EOL;
}
}
?>
We zien dat elke class zijn eigen draw() method heeft gekregen. In het kader van encapsulation en eigen verantwoordelijkheid van objecten (denk even terug aan de definitie van OOP) is deze opzet eigenlijk nog iets logischer. Een Cell bepaalt immers hoe hij in HTML code weergegeven moet worden, een Table hoort daar niets vanaf te weten. Ook zien we dat de property $_content de visibility protected heeft gekregen. Deze class gaan we zo extenden en deze property moeten we vanuit de child kunnen benaderen.
Code
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<?php
class Strong_Cell extends Cell {
public function __construct($content) {
parent::__construct($content);
}
public function draw() {
echo '<td><strong>'.$this->_content.'</strong></td>'.PHP_EOL;
}
}
?>
class Strong_Cell extends Cell {
public function __construct($content) {
parent::__construct($content);
}
public function draw() {
echo '<td><strong>'.$this->_content.'</strong></td>'.PHP_EOL;
}
}
?>
Hier zien we de Strong_Cell class, een child van de Cell class. Omdat de constructor van de child precies dezelfde functionaliteit heeft als die van de parent, is het eenvoudiger om simpel de parent constructor aan te roepen. De draw() method daarentegen heeft wel een andere functionaliteit en dus overschrijven we die in de child class. In plaats van de content in een normale cel te plaatsen, worden nu ook de <strong></strong> tags geëchoed om te zorgen dat de content dikgedrukt wordt.
De procedurele code zou er nu als volgt uit kunnen zien:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
/* Procedurele code */
$cellA1 = new Cell('Dit is cel A1');
$cellA2 = new Strong_Cell('Dit is cel A2');
$rowA = new Row();
$rowA->append($cellA1);
$rowA->append($cellA2);
$rowA->append(new Cell('Dit is cel A3')); // Zo kan het ook!
$table = new Table();
$table->append($rowA);
$table->draw();
?>
/* Procedurele code */
$cellA1 = new Cell('Dit is cel A1');
$cellA2 = new Strong_Cell('Dit is cel A2');
$rowA = new Row();
$rowA->append($cellA1);
$rowA->append($cellA2);
$rowA->append(new Cell('Dit is cel A3')); // Zo kan het ook!
$table = new Table();
$table->append($rowA);
$table->draw();
?>
Het resultaat is hier te zien en de broncode van die pagina ziet er nu als volgt uit:
Code
1
2
3
4
5
6
7
2
3
4
5
6
7
<table border="1">
<tr>
<td>Dit is cel A1</td>
<td><strong>Dit is cel A2</strong></td>
<td>Dit is cel A3</td>
</tr>
</table>
<tr>
<td>Dit is cel A1</td>
<td><strong>Dit is cel A2</strong></td>
<td>Dit is cel A3</td>
</tr>
</table>
Dit voorbeeld laat zien dat we heel eenvoudig de weergave van een cel kunnen aanpassen door bijvoorbeeld het Strong_Cell object te gebruiken. Uiteraard zou je dit veel verder kunnen uitbreiden met bijvoorbeeld een Underlined_Cell en Italic_Cell voor cellen met respectievelijk onderstreepte en cursieve inhoud.
Hier ben ik ingegaan op de weergave van bepaalde objecten, en dat terwijl ik eerder zei dat je zoveel mogelijk echo's in je classes moet proberen te voorkomen. Dat is nog steeds mijn standpunt en dit is dan ook enkel een voorbeeld. En visualisatie is nu eenmaal erg waardevol bij voorbeelden. Normaal gesproken zou je veel liever een andere oplossing kiezen voor de opmaak, zoals bijvoorbeeld het gebruik van templates.