Skip to main content

class

Een klasse (class) is een soort blauwdruk of plan voor een object. Een object is een specifiek exemplaar dat is gemaakt met de klasse. Denk aan een klasse als een koekjesvorm en het object als het koekje dat je met die vorm maakt.

class Persoon {
  String naam;
  int leeftijd;

  void begroet() {
    print('Hallo, mijn naam is $naam en ik ben $leeftijd jaar oud.');
  }
}

In dit voorbeeld is de klasse Persoon een blauwdruk die zegt dat elke Persoon een naam en een leeftijd heeft, en zichzelf kan begroeten.

Wat is een Object?

Een object is een specifiek exemplaar van een klasse. Als de klasse de koekjesvorm is, dan is het object het koekje. Je kunt meerdere objecten maken met dezelfde klasse.

void main() {
  Persoon persoon1 = Persoon('Jan', 25);
  Persoon persoon2 = Persoon('Piet', 30);
  persoon1.begroet();
  persoon2.begroet();
}

Hier maken we twee objecten persoon1 en persoon2 met de klasse Persoon.

Dart Constructors en Initializer Lists

In Dart gebruiken we een constructor om een nieuw object van een klasse te maken en de eigenschappen ervan in te stellen. Hier is een voorbeeld met de klasse Persoon.

Voorbeeldcode

Uitleg van de Code

Definiëren van de klasse Persoon:

class Persoon {
  String naam;
  int leeftijd;

We definiëren een klasse genaamd Persoon met twee eigenschappen: naam (een String) en leeftijd (een int).

Constructor met Initializer List:

Persoon(String naam, int leeftijd)
    : this.naam = naam, // Veld 'naam' wordt geïnitialiseerd
      this.leeftijd = leeftijd + 10; // Veld 'leeftijd' wordt geïnitialiseerd en met 10 verhoogd

Dit is de constructor van de klasse Persoon. Hij heeft twee parameters: naam en leeftijd. De : na de parameterlijst markeert het begin van de initializer list. this.naam = naam en this.leeftijd = leeftijd + 10 zijn initializer expressies. Ze initialiseren respectievelijk de velden naam en leeftijd van het object voordat de constructor body wordt uitgevoerd.

Methode begroet:

void begroet() {
  print('Hallo, mijn naam is $naam en ik ben $leeftijd jaar oud.');
}

Dit is een methode binnen de klasse Persoon die een begroeting uitprint met de naam en leeftijd van de persoon.

Hoofdfunctie main:

dartCode kopiërenvoid main() {
  Persoon persoon = Persoon('Jan', 25);
  persoon.begroet();
}

Hier maken we een nieuw object van de klasse Persoon met de naam ‘Jan’ en leeftijd 25. De begroet methode wordt aangeroepen om de begroeting uit te printen.

Verschil met een Eenvoudige Constructor

Een eenvoudige constructor zonder initializer list zou er als volgt uitzien:

In deze versie gebruiken we een kortere syntaxis this.naam en this.leeftijd om de velden van de klasse direct te initialiseren. In de constructor body verhogen we de leeftijd met 10.

Verschil tussen de Twee Benaderingen

De initializer list (:) wordt gebruikt om de velden te initialiseren voordat de constructor body wordt uitgevoerd. Dit is handig als je complexere initialisatie wilt doen of als je velden hebt die final zijn. In de constructor body kun je de velden initialiseren en extra logica toevoegen, wat flexibeler is maar soms minder efficiënt, omdat de velden al geïnitialiseerd moeten zijn voordat de constructor body wordt uitgevoerd.

Beide benaderingen zijn nuttig, afhankelijk van je specifieke behoefte aan initialisatie en logica in je constructor.

Final

Het trefwoord final betekent dat een variabele niet kan worden veranderd nadat deze een waarde heeft gekregen. Het is als het schrijven van iets met een pen in plaats van met een potlood.

class Persoon {
  final String naam;
  int leeftijd;

  Persoon(this.naam, this.leeftijd);
}

Hier kan de naam van een Persoon niet worden veranderd nadat deze is ingesteld.

Overerving

Overerving (inheritance) betekent dat je een nieuwe klasse kunt maken die alles van een bestaande klasse overneemt. De bestaande klasse heet de “superklasse” (superclass) of “basis klasse” (base class), en de nieuwe klasse heet de “subklasse” (subclass) of “afgeleide klasse” (derived class).

class Dier {
  void eet() {
    print('Het dier eet.');
  }
}

class Hond extends Dier {
  void blaf() {
    print('De hond blaft.');
  }
}

void main() {
  Hond hond = Hond();
  hond.eet(); // Geërfd van de klasse Dier
  hond.blaf();
}

In dit voorbeeld erft de klasse Hond van de klasse Dier. Dat betekent dat een Hond alles kan doen wat een Dier kan doen, en meer.

Het Trefwoord super

Het trefwoord super wordt gebruikt om naar de superklasse (de ouderklasse) te verwijzen. Dit is handig om de constructor van de superklasse aan te roepen.

class Dier {
  String naam;

  Dier(this.naam);

  void eet() {
    print('$naam eet.');
  }
}

class Hond extends Dier {
  Hond(String naam) : super(naam);

  void blaf() {
    print('$naam blaft.');
  }
}

void main() {
  Hond hond = Hond('Rex');
  hond.eet();
  hond.blaf();
}

Hier roept de constructor van Hond de constructor van Dier aan met super(naam).

Initializer Lists

Met initializer lists kun je variabelen instellen voordat de constructor van de superklasse wordt aangeroepen.

class Punt {
  final int x;
  final int y;

  Punt(int x, int y)
      : this.x = x,
        this.y = y;
}

void main() {
  Punt punt = Punt(2, 3);
  print('x: ${punt.x}, y: ${punt.y}');
}

In dit voorbeeld gebruiken we een initializer list om de waarden van x en y in te stellen.

Samenvatting

  • Klasse (class): Een blauwdruk voor objecten, die zegt welke eigenschappen en functies een object heeft.
  • Object: Een specifiek exemplaar van een klasse.
  • Constructor: Een speciale functie om een nieuw object te maken en eigenschappen in te stellen.
  • Final: Maakt een variabele onveranderlijk nadat deze is ingesteld.
  • Overerving (inheritance): Maakt een nieuwe klasse die alles van een bestaande klasse overneemt.
  • Superklasse (superclass): De bestaande klasse waarvan wordt overgeërfd.
  • Subklasse (subclass): De nieuwe klasse die erft van de superklasse.
  • Super: Een trefwoord om naar de superklasse te verwijzen.
  • Initializer Lists: Manier om variabelen in te stellen voordat de superklasse constructor wordt aangeroepen.

Een praktisch voorbeeld, stel je voor dat we een hele simpele takenlijst applicatie willen maken. In deze applicatie willen we taken kunnen toevoegen, markeren als voltooid, en verwijderen. Elke taak heeft een naam, een omschrijving, een prioriteit en een status die aangeeft of de taak al dan niet is voltooid.

class Taak {
  String taaknaam;
  String omschrijving;
  String prioriteit;
  bool statusTaak;

  Taak(this.taaknaam, this.omschrijving, this.prioriteit,
      [this.statusTaak = false]);

  void markeerAlsGedaan() {
    statusTaak = true;
    print("$taaknaam is gemarkeerd als gedaan.");
    return;
  }
}

In de bovenstaande code definiëren we een klasse Taak met vier eigenschappen: taaknaamomschrijvingprioriteit en statusTaak. We hebben ook een methode markeerAlsGedaan die de status van de taak verandert naar true.

Nu willen we een klasse TakenLijst maken die een lijst van taken beheert.

class TakenLijst {
  List<Taak> taken = [];

  void addTaak(Taak taak) {
    taken.add(taak);
    print("Taak toegevoegd: ${taak.omschrijving}");
    return;
  }

  void toonAlleTaken() {
    //for loop
    for (var taak in taken) {
      print("taak naam: ${taak.taaknaam} status: ${taak.statusTaak}");
    }
    return;
  }

  void toonVoltooideTaken() {
    //for loop
    for (var voltooid in taken) {
      if (voltooid.statusTaak) {
        print(voltooid.taaknaam);
      }
    }
    return;
  }

  void toonOnvoltooideTaken() {
    for (var onvoltooid in taken) {
      if (!onvoltooid.statusTaak) {
        // dus is false
        print(onvoltooid.taaknaam);
      }
    }
    return;
  }

  void markeerAlsGedaanTaak(Taak gedaan) {
    print("De taak ${gedaan.taaknaam} wordt op gedaan gezet.");
    gedaan.statusTaak = true;
    return;
  }

  void verwijderTaak(Taak taak) {
    print("De taak: ${taak.taaknaam} wordt verwijderd");
    taken.remove(taak);
    return;
  }

  int nogUitTeVoerenTaken() {
    int aantal = 0;
    for (var taak in taken) {
      if (!taak.statusTaak) {
        aantal++;
      }
    }
    return aantal;
  }
}

In de klasse TakenLijst hebben we een lijst taken die objecten van het type Taak opslaat. We hebben ook een methode addTaak die een taak aan de lijst toevoegt. De complete code ziet er als volgt uit:

void main() {
  var takenlijst = TakenLijst();

  var taak1 = Taak("Boodschappen doen", "Koop groenten en fruit", "Hoog");
  var taak2 = Taak("Studeren", "Leer voor het wiskunde examen", "Medium");
  var taak3 =
      Taak("Huis schoonmaken", "Maak de keuken en badkamer schoon", "Laag");
  var taak4 = Taak("Auto wassen", "Was de auto in de garage", "Laag");
  var taak5 =
      Taak("Boek lezen", "Lees het nieuwe boek van de bibliotheek", "Medium");
  var taak6 = Taak("Sporten", "Ga naar de sportschool", "Hoog");
  var taak7 = Taak("Koken", "Maak avondeten voor de familie", "Hoog");

  print(" # Begin taken toevoegen.");
  takenlijst.addTaak(taak1);
  takenlijst.addTaak(taak2);
  takenlijst.addTaak(taak3);
  takenlijst.addTaak(taak4);
  takenlijst.addTaak(taak5);
  takenlijst.addTaak(taak6);
  takenlijst.addTaak(taak7);
  print(" # Einde taken toevoegen\n\n");

  print(" # All taken zijn: ");
  takenlijst.toonAlleTaken();

  print("\n\n # taken markeren als gedaan");
  taak1.markeerAlsGedaan();
  takenlijst.markeerAlsGedaanTaak(taak4);
  taak7.markeerAlsGedaan();

  print("\n\n # taken voltooide taken:");
  takenlijst.toonVoltooideTaken();

  print("\n\n # taken onvoltooide taken:");
  takenlijst.toonOnvoltooideTaken();

  print("\n\n # 2 taken verwijderen:");
  takenlijst.verwijderTaak(taak2);
  takenlijst.verwijderTaak(taak5);

  print("\n\n # toon de overbleven taken:");
  takenlijst.toonAlleTaken();

  print("\n\nEr zijn nog ${takenlijst.nogUitTeVoerenTaken()} uit te voeren");

  print("Er zijn in totaal ${takenlijst.taken.length} taken.");
}

class Taak {
  String taaknaam;
  String omschrijving;
  String prioriteit;
  bool statusTaak;

  Taak(this.taaknaam, this.omschrijving, this.prioriteit,
      [this.statusTaak = false]);

  void markeerAlsGedaan() {
    statusTaak = true;
    print("$taaknaam is gemarkeerd als gedaan.");
    return;
  }
}

class TakenLijst {
  List<Taak> taken = [];

  void addTaak(Taak taak) {
    taken.add(taak);
    print("Taak toegevoegd: ${taak.omschrijving}");
    return;
  }

  void toonAlleTaken() {
    //for loop
    for (var taak in taken) {
      print("taak naam: ${taak.taaknaam} status: ${taak.statusTaak}");
    }
    return;
  }

  void toonVoltooideTaken() {
    //for loop
    for (var voltooid in taken) {
      if (voltooid.statusTaak) {
        print(voltooid.taaknaam);
      }
    }
    return;
  }

  void toonOnvoltooideTaken() {
    for (var onvoltooid in taken) {
      if (!onvoltooid.statusTaak) {
        // dus is false
        print(onvoltooid.taaknaam);
      }
    }
    return;
  }

  void markeerAlsGedaanTaak(Taak gedaan) {
    print("De taak ${gedaan.taaknaam} wordt op gedaan gezet.");
    gedaan.statusTaak = true;
    return;
  }

  void verwijderTaak(Taak taak) {
    print("De taak: ${taak.taaknaam} wordt verwijderd");
    taken.remove(taak);
    return;
  }

  int nogUitTeVoerenTaken() {
    int aantal = 0;
    for (var taak in taken) {
      if (!taak.statusTaak) {
        aantal++;
      }
    }
    return aantal;
  }
}