Classes & objecten
- Voorbeeld
- Classbeschrijving maken
- Object maken
- Meerdere objecten maken
- Meerdere objecten in een array
- Eigenschappen meegeven aan een object
- Eigenschappen meegeven aan methods
Een class is een manier om bepaalde functies en variabelen die samenhangen in één keer te beschrijven. Dit doe je zodat je er makkelijk heel veel van kunt maken zonder daar steeds allerlei nieuwe variabelen voor te declareren.
Binnen programmeertalen zijn objecten taalconstructies waarmee je groepen van verschillende elementen kunt maken. Dat doe je niet achteraf door elementen toe te voegen aan een groep, maar van te voren door een klasse te beschrijven en vervolgens dingen te maken die de eigenschappen van die klasse hebben. Die dingen noem je objecten. Binnen JavaScript bestaat er nog een andere vorm van objecten. Als we het in dit hoofdstuk over objecten hebben bedoelen we de hierboven beschreven vorm.
1. Voorbeeld
Als we in P5.js een blokje op het scherm willen tekenen dan kunnen we de functie rect
aanroepen om een rechthoek te tekenen. We moeten elke keer bedenken waar de rechthoek moet staan (x- en y-positie) en hoe groot hij is (breedte en hoogte (b,h)) Verder moeten we aangeven in welke kleur hij getekend moet worden, of er een rand omheen moet en als we hem willen verplaatsen of laten knipperen moet daar ook code voor worden geschreven.
Dat is voor één blokje nog wel te doen, maar als je meerdere blokjes wil tekenen die elkaar onderling beïnvloeden, dan wordt de code al gauw onoverzichtelijk.
Dat kan ook anders: we beschrijven eerst het algemene gedrag van een blokje in een object en daarna kunnen we zo veel van die blokjes maken als we nodig hebben.
2. Ontwerp: een class-beschrijving maken
Vraag jezelf van te voren af: welke algemene eigenschappen heeft een blokje en welke functionaliteiten moet deze krijgen? In dit geval zijn de eigenschappen positie, afmeting, kleur, omlijning. De belangrijste functionaliteit is dat het blokje getekend moet worden.
class Block {
constructor() {
this.x = random(width); //x-positie
this.y = random(height); //y-positie
this.b = random(10, 50); //breedte
this.h = random(10, 50); //hoogte
this.blockColor = color(random(255), random(255), random(255)); //kleur
}
draw() {
fill(this.blockColor);
rect(this.x, this.y, this.b, this.h);
}
}
De hierboven beschreven code is de minimale opzet van een class. Het aanmaken van de class gebeurt met het woord class
waarna de naam van de class volgt. Het is een goed gebruik, en in sommige gevallen zelfs verplicht, om deze naam met een hoofdletter te laten beginnen.
let op: in tegenstelling tot bij het maken van een functie volgen er geen () na het maken van een class, het is immers geen functie, waar de ()
wel verplicht zijn.
2.1 Methods
Vervolgens kan je binnen een class met behulp van verschillende methods eigenschappen en gedrag van een object gaan bepalen. Een method is een vergelijkbare constructie als een functie, maar dan binnen een object.
let op: in tegenstelling tot bij het maken van een functie hoef je niet het woord function
op te schrijven voordat je een method binnen een class aanmaakt.
2.2 Constructor
Een belangrijke method is de constructor()
. De constructor wordt aangeroepen zodra je vanuit de class-beschrijving een nieuw object aanmaakt. Je kan de constructor vergelijken met de setup()
-functie uit P5.js: De plek om algemene eigenschappen te beschrijven.
2.3 Variabelen
variabelen die je binnen een class wilt gebruiken definieer je net anders dan in normale JavaScript-code. Dit doe je door this.
te gebruiken. Met this.
zorg je ervoor dat de variabele uiteindelijk alleen bekend is binnen het object dat je hebt aangemaakt, en daarmee dus ook exclusief is voor dat object. Zo kan je bij het maken van meerdere objecten uit één class-omschrijving er voor zorgen dat ieder object unieke eigenschappen heeft.
3. Realisatie: een object maken
Een nieuw object wordt doormiddel van new
met daaropvolgend de naam van de class, afgesloten met ()
. Een nieuwe object plaats je in een variabele, zodat je er later nog iets mee kunt. De constructor-method wordt automatisch uitgevoerd zodra je op deze manier een object maakt van een classbeschrijving.
Voorbeeld: myBlock = new Block();
Zodra je het object hebt gemaakt kan je de methods die je binnen dit object hebt gemaakt aanroepen op de volgende manier: naam van de variabele.naam van de functie()
.
Voorbeeld myBlock.draw();
.
In het hieronder beschreven voorbeeld wordt het object aangemaakt in de setupfunctie, dit kan niet daarboven omdat de inhoud van de class-beschrijving nog niet bekend is als dat deel van de code uitgevoerd wordt. Zodra de setup()
-functie wordt uitgevoerd is die beschrijving wel bekend en kan je het object maken.
//lege variabele waar straks een object in opgeslagen wordt
let myBlock;
function setup() {
createCanvas(600 ,800);
//hieronder maken we een nieuw object vanuit de class Block
// op dat moment wordt de constructor()-method aangeroepen
myBlock = new Block();
}
function draw() {
background(200);
//hier wordt de draw()-method uti de classomschrijving uitgevoerd
myBlock.draw();
}
//class-beschrijving:
class Block {
constructor() {
this.x = random(width); //x-positie
this.y = random(height); //y-positie
this.b = random(10, 50); //breedte
this.h = random(10, 50); //hoogte
this.blockColor = color(random(255), random(255), random(255)); //kleur
}
draw() {
fill(this.blockColor);
rect(this.x, this.y, this.w, this,h);
}
}
4. Meerdere objecten maken
Zoals je hieronder ziet kan je meerdere variabelen aanmaken en die vervolgens allemaal vullen met een nieuw object. Op die manier maak je dus met behulp van een class-beschrijving meerdere objecten aan. Doordat in de constructor()
-method de positie, grootte en kleur willekeurig wordt bepaald, zal elk object, myBlock1, myBlock2 en myBlock3 een andere positie, grootte en kleur hebben.
let myBlock1;
let myBlock2;
let myBlock3;
function setup() {
createCanvas(800,600);
myBlock1 = new Block();
myBlock2 = new Block();
myBlock3 = new Block();
}
function draw() {
background(200);
myBlock1.draw();
myBlock2.draw();
myBlock3.draw();
}
class Block {
constructor() {
this.x = random(width); //x-positie
this.y = random(height); //y-positie
this.b = random(10, 50); //breedte
this.h = random(10, 50); //hoogte
this.blockColor = color(random(255), random(255), random(255)); //kleur
}
draw() {
fill(this.blockColor);
rect(this.x, this.y, this.w, this,h);
}
}
5. Meerdere objecten en arrays
Zodra je meerdere objecten wil gaan aanmaken vanuit één class-beschrijving dan wil je natuurlijk niet voor elk object een aparte variabele moeten maken. Dat is nog wel te doen bij 3 objecten, maar als je er 100 wil aanmaken wordt dat al snel lastig. Om dat probleem op te lossen kan je objecten ook in een array
opslaan en met een for()
-loop een x-aantal keer een nieuw object op een array-positie plaatsen. Vervolgens kun je ook met een for()
-loop van elk object dat in de array
staat een of meerdere methods aanroepen.
let blockAmount = 10;
let blockArray = [];
function setup() {
createCanvas(800, 600);
//de loop wordt zo vaak herhaald als het aantal in
// de variabele blokckAmount
for (let i = 0; i < blockAmount; i++) {
//op positie 0 t/m 9 wordt een nieuw object
//geplaatst dat gebaseerd is op de Block-
//class-omschrijving
blockArray.push(new Block());
}
}
function draw() {
background(200);
//de loop wordt zo vaak herhaald als het aantal in
// de variabele blokckAmount
for (let i = 0; i < blockAmount; i++) {
//van elk object in de array wordt de method
//draw() aangeroepen, de rechthoek wordt getekend
blockArray[i].draw();
}
}
class Block {
constructor() {
this.x = random(width); //x-positie
this.y = random(height); //y-positie
this.b = random(10, 50); //breedte
this.h = random(10, 50); //hoogte
this.blockColor = color(random(255), random(255), random(255)); //kleur
}
draw() {
fill(this.blockColor);
rect(this.x, this.y, this.w, this,h);
}
}
6. Eigenschappen meegeven aan een object
Soms is het nodig om vanuit de setup()
-functie een of meerdere eigenschappen (arguments
) mee te geven aan een object, bijvoorbeeld als je de positie wilt laten afhangen van het aantal objecten dat je maakt. Dat kan door argumenten mee te geven bij het aanmaken van het object. Deze argumenten worden vervolgens in de constructor()
-functie in de class binnengehaald.
In de onderstaande code zijn twee dingen aangepast ten opzichte van de code daarboven:
- Bij het aanmaken van het nieuwe object wordt er als argument
(width / blockAmount) * i
meegegeven. Dit zorgt ervoor dat het aantal blokken evenredig verdeeld worden over de breedte van het canvas. - in de
costructor()
-method in de class-beschrijving isnewX
tussen de haakjes toegevoegd. let op:newX
is een andere variabele danthis.x
.newX
is alleen geldig binnen deconstructor()
-method.this.x
is bekend binnen het hele object. Doorthis.x
de waarde vannewX
te geven zal je dus van elk object kunnen bepalen wat hiervan de x-positie wordt.
let blockAmount = 10;
let blockArray = [];
function setup() {
createCanvas(800,600);
for (let i = 0; i < blockAmount; i++) {
blockArray[i] = new Block((width / blockAmount) * i);
}
}
function draw() {
background(200);
for (let i = 0; i < blockAmount; i++) {
blockArray[i].draw();
}
}
class Block {
constructor(newX) {
this.x = newX; //x-positie
this.y = random(height); //y-positie
this.b = random(10, 50); //breedte
this.h = random(10, 50); //hoogte
this.blockColor = color(random(255),random(255),random(255)); //kleur
}
draw() {
fill(this.blockColor);
rect(this.x, this.y, this.w, this,h);
}
}
7. Eigenschappen meegeven aan methods
Net als dat je eigenschappen als argument mee kan geven aan een object via de constructor()
-method, kan je ook aan de andere methods die je hebt aangemaakt in je class-omschrijving argumenten meegeven. Bijvoorbeeld als je iets dat in de algemene code gebeurt invloed wil laten hebben op een of meerdere objecten die je hebt gemaakt.
In het voorbeeld hieronder is er een argument meegegeven aan de draw()
-method zodat het vierkant alleen getekend wordt, als de x-positie van de muis hoger is dan de x-positie van het betreffende object. Daarvoor zijn drie aanpassingen nodig:
- de
draw()
-method in de class-omschrijving krijgt een variabele als argument tussen de()
->draw(mousePos)
- in de
draw()
-method wordt een if-statement toegepast om te kijken ofmousePos
groter is danthis.x
- in de globale
draw()
-functie van de P5.js-sketch wordt de globale variabele mouseX meegegeven als argument bij het aanroepen van dedraw()
-method ->blockArray[i].draw(mouseX)
let blockAmount = 10;
let blockArray = [];
function setup() {
createCanvas(800,600);
for (let i = 0; i < blockAmount; i++) {
blockArray[i] = new Block((width / blockAmount) * i);
}
}
function draw() {
background(200);
for (let i = 0; i < blockAmount; i++) {
blockArray[i].draw(mouseX);
}
}
class Block {
constructor(newX) {
this.x = newX; //x-positie
this.y = random(height); //y-positie
this.b = random(10, 50); //breedte
this.h = random(10, 50); //hoogte
this.blockColor = color(random(255),random(255),random(255)); //kleur
}
draw(mousePos) {
if(mousePos > this.x) {
fill(this.blockColor);
rect(this.x, this.y, this.w, this,h);
}
}
}