OOP: Classes & Objects

In deze tutorials is het de bedoeling dat je een ruimer beeld krijgt over OOP en de daarbij horende toepassingen.
Het meeste in deze tutorials is taal-onafhankelijk, maar als voorbeeldtaal gaan we PHP gebruiken omdat dit vrij gekend is en een zeer kleine leercurve heeft ten opzichte van de andere moderne programmeertalen. Ik moet hier wel bij vermelden dat PHP eigenlijk niet zo’n goede taal is om OOP in te leren vanwege z’n syntax en z’n weak typing oa. (meer daarover in volgende tutorials).

Tijdens deze tutorials zullen we allerlei zaken bespreken zoals:

  • Basics
  • APIE
  • Design principes
  • Design patterns

In deze eerste tutorial gaan we de basics behandelen, zoals de betekenis van:

  • Classes & Objects
  • Overerving
  • Constructor
  • Static Context

Wat is OOP?
OOP staat voor object-oriented programming of in het Nederlands objectgeoriënteerd programmeren. Het is een manier van developen, maar ook van nadenken.
Alles wat in deze wereld staat, groeit, leeft en niet leeft kan je gemakkelijk vertalen naar een OO context en dus ook omzetten in OOP.

De wereld bestaat eigenlijk uit blueprints met daar telkens afgeleiden van.
Een voorbeeld: Ieder mens heeft 2 benen, 2 armen, 10 vingers, 10 tenen, … . De algemene context of blueprint noemen we in OOP een class.
Doch is elk mens verschillend, we hebben namelijk elk ons eigen status en gedrag. Deze implementatie van ‘een mens’ noemen we een instance (instantie) of een object van de class ‘Mens’.

Status en gedrag
Status en gedrag zijn de 2 zaken die ervoor zorgen dat elke instantie van een class er anders uit ziet, net zoals er op deze planeet geen 2 dezelfde mensen rondlopen.
In onze programmeertaal zetten we dit om in velden en methodes.

In de velden gaan we de status van een object bewaren. Ze bevatten de gegevens over iemand, zoals dat mijn naam ‘Dimitri’ is, en die van iemand anders ‘Jan’ zal zijn.
Als je twee verschillende mensen naast elkaar plaatst en laat lopen, zal je zien dat geen enkele persoon precies op dezelfde manier loopt. Dit noemen we het gedrag van een instantie en kunnen we vastleggen door middel van methodes.

Overerving
Overerving is één van de vier grote peilers in OOP die ik tijdens de volgende tutorial zal bespreken. Maar om van OOP iets te begrijpen moet je ook begrijpen waarom het zo goed werkt.
Een van de redenen waarom OOP goed werkt is overerving. Overerving zorgt ervoor dat je code kan herbruiken.
Een voorbeeld je hebt een class ‘Kip’ en een andere ‘Eend’. Dit zijn 2 verschillende dieren die heel verschillend zijn maar toch ook vergelijkbaar zijn, het zijn namelijk allebei vogels die eieren leggen en nog honderden andere overeenkomsten hebben, maar nog meer verschillen hebben ook.

Om ervoor te zorgen dat we niet alles in zowel ‘Kip’ als ‘Eend’ moeten voorzien, kunnen we een class ‘Vogel’ aanmaken waar alle overeenkomsten in terecht komen. Nadien moeten we dan op de één of andere manier zeggen dat ‘eend’ en ‘kip’ een ‘vogel’ zijn, en dat is waar overerving voor dient.

‘Vogel’ is hierdoor een super-class geworden van ‘Kip’ en ‘Eend’. Anderzom kunnen we zeggen dat ‘Kip’ en ‘Eend’ sub-classes zijn van ‘Vogel’.

Access Modifiers
Iets enorm belangrijk bij OOP is de zichtbaarheid van velden en methodes. Soms wil je er namelijk voor zorgen dat andere objecten niet zomaar overal aan kan. Je wilt bijvoorbeeld niet dat een andere mens ervoor kan zorgen dat hij de methode ‘denk’ bij jou kan oproepen, dit wil jij namelijk alleen zelf doen.
In OOP hebben ze daarom de access modifiers uitgevonden. Deze zorgen ervoor dat sommige methodes en velden niet zichtbaar zijn van buitenaf, maar wel in de instantie zelf. Er zijn drie access modifiers:

  • public
  • protected
  • private

public is zoals de naam het zegt, publiek voor iedereen. Dit zijn de methodes en velden die van buitenaf toegankelijk zijn en waar dus iedereen aan kan.
protected is minder zichtbaar dan public. Het zorgt er namelijk voor dat de zichtbaarheid beperkt wordt tot de instantie zelf EN alle instanties van subclasses ervan.
private ten slotte is het minst zichtbaar. Het zorgt er namelijk voor dat je er enkel aan kan vanuit de eigen class.

Een eerste code-voorbeeld:

<?php

/**
 * Dit is onze eerste class of blueprint van een 'Vogel'.
 * De bedoeling is dat het een vereenvoudigde weergave is van de realiteit.
 */
class Vogel {
	protected $vleugels = 2; // Dit is een veld, zij leggen de status van een object vast

	public function LegEi() { // Dit is een methode, zij leggen het gedrag van een object vast
		return "*Legt een ei*";
	}

	public function Beweeg() {
		return "*Vliegt met ". $this->vleugels ." vleugels*";
	}
}

class Kip extends Vogel { // extends is het keyword dat gebruikt wordt bij overerving

	public function Beweeg() {
		return "*Loopt*";
	}
}

class Eend extends Vogel {

	public function Beweeg() {
		return "*Zwemt*" . parent::Beweeg(); // parent gebruik je bij het aanroepen van de super-class
	}
}

$vogel = new Vogel(); // Een instantie maken van de blueprint 'Vogel'
$kip = new Kip();
$eend = new Eend();

echo "<h1>Vogel</h1>". $vogel->Beweeg() ."<br />". $vogel->LegEi() ."<br />"; // Methodes oproepen

// We roepen de LegEi methode op, maar aangezien die niet in Kip staat, krijgen we die van een Vogel te zien
echo "<h1>Kip</h1>". $kip->Beweeg() ."<br />". $kip->LegEi() ."<br />";

// De Beweeg-methode roept zowel de eigen Beweeg-methode op, als die van de super-class.
echo "<h1>Eend</h1>". $eend->Beweeg() ."<br />". $eend->LegEi() ."<br />";

?>

Dit voorbeeld is het Vogel-Kip-Eend voorbeeld besproken in het deel over overerving.

Constructor
Bij het aanmaken van een instantie van een bepaalde class, heb je in voorgaande code gezien dat je daarvoor het keyword new gebruikt. Het eerste wat er dan gedaan wordt bij het aanmaken van een object, is het aanroepen van een constructor.
Een constructor kan je zien als een speciale methode, die ervoor zorgt dat een object geïnitializeerd wordt. Hier kan je dus bepaalde velden gaan initializeren om er later gebruik van te kunnen maken.

Een voorbeeld:

<?php

class Mens {

	// Veld
	private $naam;

	// De constructor van de class Mens, let ook op dat we hier gebruik maken van parameters
	public function __construct($n) {
		$this->naam = $n;
	}

	// Getter voor de naam, let op dat we hier gebruik maken van een return
	public function GetNaam() {
		return $this->naam;
	}
}

$mens = new Mens("Dimitri");
echo "Mens: ". $mens->GetNaam();

?>

Static context
Soms wil je helemaal niet dat je een instantie moet aanmaken alvorens je ermee kan werken. Dit is van toepassing bij classes die geen eigen gedrag of status moeten beschikken. Voorbeelden hiervan zijn verwerkings-classes.
Als je een class ‘Bewerkingen’ zou hebben, dan is het vrij vreemd dat je hiervoor een eigen instantie voor aanmaakt, maar dat je rechtstreeks de bewerking kan uitvoeren.

Een voorbeeld:

<?php

class Bewerkingen {

	// Statische methode
	public static function Optellen($getal1, $getal2) {
		return $getal1 + $getal2;
	}
}

/**
 * Let erop dat we nu niet gebruik maken van het keyword 'new'.
 * Aangezien er gene instantie aangemaakt wordt, wordt er dus ook geen constructor gebruikt.
 */
echo "Som: ". Bewerkingen::Optellen(2, 3);

?>

Objectgeoriënteerd vs functioneel programmeren
De meeste web-developers onder ons zijn het gewend om functioneel te programmeren. Functioneel programmeren is volgens mij heel handig bij kleine problemen, maar vanaf dat je met meerdere mensen aan één project bezig bent of zelfs je code deelt met anderen, dan is functioneel programmeren veel moeilijker.
Bij functioneel programmeren kan je vrij snel beginnen met programmeren, omdat er weinig achterliggende structuur nodig is. Maar het nadeel is dat door het gebrek aan structuur, je ook heel moeilijk bepaalde regels kan vastleggen voor anderen die aan je code willen werken (met hooks).
Bij OOP daarentegen kan je minder snel beginnen aan het programmeren, maar moet je beginnen met plannen. Je moet op voorhand bepalen welke classes je nodig hebt en hoe zij met elkaar communiceren. Door middel van abstractie (zal in volgende tutorial besproken worden) is het ook mogelijk bepaalde stukken code vast te leggen terwijl anderen dan weer open zijn voor implementatie.

Einde
Dit is het einde van de eerste (vrij korte) tutorial over OOP. Tijdens de volgende tutorial zullen we beginnen met het échte werk en gaan we APIE onder handen nemen.
APIE staat voor:

  • Abstraction
  • Polymorphism
  • Inheritance
  • Encapsulation

Deze zaken zijn de 4 grote peilers in OOP die ervoor zorgen dat het zo goed werkt, maar meer daarover in de volgende tutorial.

Tagged , , .

g00glen00b

IT Consultant with a passion for JavaScript. Experienced in the Spring Framework and various JavaScript frameworks.

  • Bedankt voor deze nuttige uitleg. Het is me niet helemaal duidelijk wat de vervolg tutorial is. Hieronder staan <> Een AJAX chatsysteem… of zit er geen volgorde in je tutorials?