We weten dat een klasse een soort machine is, die objecten kan produceren. Dat wil zeggen dat als we “object georienteerd” willen gaan programmeren, dat we moeten nadenken vanuit de objecten die we willen maken, en niet meer vanuit de structuur van een geheel programma.
Laten we de bewegende zwarte cirkel uit de oefening van functies er even terug bij nemen:
int x = 0; int y = 100; int snelheid = 1; void setup() { size(200,200); } void draw() { background(255); updateCirkel(); testCirkel(); tekenCirkel(20); } void updateCirkel(){ x = x + snelheid; } void testCirkel(){ if(x > width || x < 0){ snelheid = snelheid * -1; } } void tekenCirkel(int diam){ fill(0); ellipse(x,y, diam, diam); }
Verschillende bewegende cirkels
Vorige les hebben we geleerd dat we functies kunnen schrijven op zo’n manier, dat we parameters kunnen doorgeven. We hebben een functie gebouwd die verschillende cirkels met verschillende diameters produceerde, en een functie die een waarde van Celsius naar Fahrenheit kon omzetten.
Waarom kunnen we zo’n functie dan niet gebruiken om verschillende bewegende cirkels te tekenen? Het probleem zit hem in het gebruik van lokale en globale variabelen, en het verschil tussen beide.
Wanneer we een functie maken, met de bedoeling cirkels te produceren die op verschillende posities, onafhankelijk van elkaar bewegen, dan lopen we tegen een probleem aan:
void setup(){ size(300,300); } void draw(){ background(255); drawBlackCircle(20,20); drawBlackCircle(50,50); } void drawBlackCircle(int x, int y){ fill(0); ellipse(x,y, 50,50); x = x +1; }
Ik verwacht dat dit programma 2 zwarte cirkels tekent:
- 1 op x-coordinaat 20, y-coordinaat 20
- 1 op x-coordinaat 50, y-coordinaat 50
Vervolgens bewegen deze cirkels beiden naar rechts via de code: x = x +1;
dit is echter niet wat er gebeurt:
De reden hiervoor is dat de waarden (20,20) en (50,50) in een lokale variabele binnen de functie terechtkomen. Daar wordt er 1 bijgeteld, maar op het einde van de functie worden deze variabelen vernietigd. Op deze manier wordt de waarde niet voor langere tijd vastgehouden. De volgende diagram geeft de flow weer van wat er gebeurt.
Wanneer we dus deze cirkels afzonderlijk van elkaar willen laten bewegen, met elk hun eigen snelheid, dan zullen we globale variabelen moeten gebruiken. Globale variabelen worden namelijk in de loop van een programma niet automatisch verwijderd en zijn dus geschikt om een waarde voor langere tijd bij te houden.
Het probleem is dan dat we voor elke nieuwe cirkel eigen globale variabele moeten aanmaken. Deze globale variabelen kunnen we niet meegeven als parameters in de functie, want dan worden de waardes op het einde van de functie weer gereset. Parameters doorgeven werkt dus niet. Onze functie is niet meer te hergebruiken op deze manier, dus elke cirkel heeft ook zijn eigen functie nodig om afzonderlijk te bewegen:
int x1 = 20; int x2 = 50; int y1 = 20; int y2 = 50; int snelheid1 = 1; int snelheid2 = 2; void setup(){ size(300,300); } void draw(){ background(255); drawBlackCircle1(); drawBlackCircle2(); } void drawBlackCircle1(){ fill(0); ellipse(x1,y1, 50,50); x1 = x1 + snelheid1; } void drawBlackCircle2(){ fill(0); ellipse(x2,y2, 50,50); x2 = x2 + snelheid2; }
Je merkt dat deze manier van werken een grote stap achterwaarts is. Op deze manier kunnen we nooit grotere, schaalbare programma’s maken met objecten die op zichzelf kunnen bestaan. We willen dat onze cirkels elk hun eigen globale variabelen kunnen bezitten, onafhankelijk van het hoofdprogramma. Om dat te kunnen doen hebben we objecten en klassen nodig.