- Bij compositie maakt de klasse haar onderdelen zelf aan, met
newbij de instantievariabele of in de constructor. Bij aggregatie krijgt ze het object binnen via een parameter of property, en het blijft ook zonder haar bestaan (uitleg). - Een interne lijst is een private instantievariabele, zonder property. Van buitenaf werk je ermee via je eigen methoden, zoals
VoegToe. Een publicgetgeeft de echte lijst, en daarop werktClear()gewoon, ook metprivate set(uitleg). - Een object als instantievariabele is
nulltot er een object in komt. Controleer opnullvoor je het gebruikt (uitleg). thisis het object zelf. Zo geef je jezelf mee aan een methode (coach.VoegSporterToe(this)), enthis.naam = naam;lost een naamconflict met een parameter op. In eenstaticmethode bestaatthisniet (uitleg).
UML naar code (Essential)
Een UML-diagram toont welke klasse welke andere klasse bevat. Zo lees je het:
- Elk blokje wordt een klasse, ook als er verder niets in staat.
- Een lijn met een volle ruit is compositie. De ruit staat aan de kant van de klasse die het onderdeel heeft. Die klasse maakt het onderdeel zelf aan: bij de instantievariabele of in de constructor.
- Een lijn met een lege ruit is aggregatie. Het onderdeel wordt buiten de klasse aangemaakt en komt binnen via een property of een methode.
- Het getal aan de kant van het onderdeel zegt hoeveel er zijn.
1..4betekent minstens 1 en hoogstens 4. Zijn het er meer dan één, dan wordt het eenList. Het getal aan de andere kant (0..1bijMotor) moet je niet programmeren. - De onderdelen zijn private.
Deel 1. Een persoon heeft een hoofd, twee handen en twee benen. Geef Persoon een ToString die Persoon met 2 handen en 2 benen teruggeeft, en tel daarvoor de elementen in je lijsten.

Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
Deel 2. Een groter diagram. Een motor krijgt in zijn constructor mee hoeveel zuigers hij heeft, een boot krijgt mee hoeveel schroeven hij heeft en hoeveel zuigers zijn motor heeft. Een auto heeft altijd een motor met 4 zuigers. Klopt een aantal niet met het diagram, dan werpt de constructor een ArgumentException op.
Geef Motor, Auto en Boot een ToString. Die van Auto en Boot gebruikt de ToString van hun motor.

Testcode. Je code werkt als je exact deze uitvoer krijgt.
Auto auto = new Auto();
Console.WriteLine(auto);
Boot boot = new Boot(2, 6);
Console.WriteLine(boot);
try
{
Boot vlot = new Boot(0, 4);
}
catch (ArgumentException e)
{
Console.WriteLine(e.Message);
}
try
{
Motor monster = new Motor(12);
}
catch (ArgumentException e)
{
Console.WriteLine(e.Message);
}Auto met 4 wielen en een motor met 4 zuigers
Boot met 2 schroeven en een motor met 6 zuigers
Een boot heeft 1 tot 4 schroeven.
Een motor heeft 4 tot 8 zuigers.
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
Deel 3. Dit diagram uit het boek combineert beide soorten ruiten. Een huis maakt zijn slaapkamer en badkamer zelf. De computer en zijn onderdelen worden buiten de klasse aangemaakt: Computer heeft daarvoor drie properties: Schijf van het type HardeSchijf, Processor van het type Processor en Geluidskaart van het type Geluidskaart. Slaapkamer heeft een property Computer van het type Computer. Een property mag dezelfde naam hebben als haar type. Omdat de slaapkamer private is, krijgt Huis een methode PlaatsComputer(Computer computer) die de computer in de slaapkamer zet.
ToString van Computer telt hoeveel onderdelen er al in zitten. ToString van Slaapkamer en van Huis zie je in de uitvoer hieronder.

Testcode. Je code werkt als je exact deze uitvoer krijgt.
Computer pc = new Computer();
pc.Schijf = new HardeSchijf();
pc.Processor = new Processor();
Huis huis = new Huis();
Console.WriteLine(huis);
huis.PlaatsComputer(pc);
Console.WriteLine(huis);
huis = null; // het huis brandt af, de computer is gered
pc.Geluidskaart = new Geluidskaart();
Console.WriteLine(pc);Huis met een badkamer en een slaapkamer zonder computer
Huis met een badkamer en een slaapkamer met computer met 2 onderdelen
computer met 3 onderdelen
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
- Een volle ruit wordt een
newin de klasse zelf, een lege ruit een property of methode waarlangs het object binnenkomt. Zie Associaties beschrijven. - Na
huis = null;werktpcgewoon verder:Mainheeft nog een verwijzing naar de computer. De slaapkamer bereik je niet meer, die verdwijnt met het huis. - Een
ToStringmag deToStringvan zijn onderdelen gebruiken:$"... een {motor}".
Voorspel de uitvoer: mag ik je laptop even? (Essential)
Groepswerk in de bib. De laptop van Tom doet het niet, dus werkt hij op die van Jana. Er zijn drie klassen:
internal class Batterij
{
public int Procent { get; set; } = 100;
}internal class Laptop
{
private Batterij batterij = new Batterij();
public string Sticker { get; set; }
public Laptop(string Sticker)
{
Sticker = Sticker.ToUpper();
}
public int BatterijProcent
{
get { return batterij.Procent; }
}
public void Gebruik(int uren)
{
batterij.Procent -= uren * 20;
}
}internal class Student
{
public string Naam { get; set; }
public Laptop Laptop { get; set; }
}En dit is Main:
Laptop laptop = new Laptop("ap");
Student jana = new Student() { Naam = "Jana", Laptop = laptop };
Student tom = new Student() { Naam = "Tom" };
Console.WriteLine($"Sticker: {laptop.Sticker}");
tom.Laptop = jana.Laptop;
tom.Laptop.Gebruik(3);
Console.WriteLine($"Jana: {jana.Laptop.BatterijProcent}%");
jana = null;
Console.WriteLine($"Tom: {tom.Laptop.BatterijProcent}%");
Student lotte = new Student() { Naam = "Lotte" };
Console.WriteLine($"Lotte: {lotte.Laptop.BatterijProcent}%");Deel 1. Er zijn twee “heeft een”-relaties: een laptop heeft een batterij, een student heeft een laptop. Welke is compositie, welke aggregatie? Wijs telkens de lijn aan die het verraadt.
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
Deel 2. Schrijf op papier wat dit programma toont, lijn per lijn. Wat gebeurt er op de laatste lijn? Typ de code pas daarna over en vergelijk. De groene kronkels CS8618 en CS8600 mag je laten staan.
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
Deel 3. Herstel de constructor van Laptop met this, zodat de eerste lijn Sticker: AP toont. Pas daarna de laatste lijn van Main aan: heeft Lotte geen laptop, dan toont het programma Lotte heeft geen laptop.
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
- Wie doet
new? Doet de klasse het zelf, dan is het compositie. Komt het object binnen, dan is het aggregatie. Zie Associatie in de praktijk. - Een object toekennen maakt geen kopie: beide variabelen wijzen naar hetzelfde object, net als bij het hart van de donor in Associatie of overerving?
- Heeft een parameter dezelfde naam als een property of instantievariabele, dan bereik je die laatste enkel nog met
this. Zie Het this keyword.
Zelf je gaming-pc bouwen
Met het geld van je studentenjob stel je zelf een gaming-pc samen. Alles komt op het moederbord: een processor, een grafische kaart in het PCIe-slot, en RAM-latjes in de RAM-sloten.

Maak deze klassen:
ProcessorenGrafischeKaart, elk met eenNaamdie je via de constructor meegeeft.RamLatjemet eenMerken een aantalGigabyte, ook via de constructor.Moederbordmet eenNaamen een aantal RAM-sloten, allebei via de constructor.
De processor en de grafische kaart koop je los en steek je erin: dat is aggregatie, dus Moederbord heeft voor elk een property Processor en GrafischeKaart. Zolang je er niets in stak, zijn ze null.
De RAM-sloten zijn een private array van RamLatje, met evenveel plaatsen als er sloten zijn. Een leeg slot is null. Van buitenaf kan je er enkel aan via twee methoden:
PlaatsRam(RamLatje latje)steekt het latje in het eerste vrije slot. Zijn alle sloten vol, dan toont zeGeen vrij RAM-slot meer voor de ... van ... GB.TestMoederbord()toont wat er nog ontbreekt, plus hoeveel RAM-sloten vrij zijn en hoeveel gigabyte er in totaal geplaatst is.
Testcode. Je code werkt als je exact deze uitvoer krijgt.
Moederbord bord = new Moederbord("Z790 Gaming", 2);
bord.TestMoederbord();
Console.WriteLine("---");
bord.Processor = new Processor("Intel Core i5-14600K");
bord.PlaatsRam(new RamLatje("Corsair", 16));
bord.PlaatsRam(new RamLatje("Corsair", 16));
bord.PlaatsRam(new RamLatje("Kingston", 8));
bord.TestMoederbord();
Console.WriteLine("---");
bord.GrafischeKaart = new GrafischeKaart("GeForce RTX 4060");
bord.TestMoederbord();Nog geen processor
Nog geen grafische kaart in het PCIe-slot
2 van de 2 RAM-sloten vrij, 0 GB geplaatst
---
Geen vrij RAM-slot meer voor de Kingston van 8 GB.
Nog geen grafische kaart in het PCIe-slot
0 van de 2 RAM-sloten vrij, 32 GB geplaatst
---
0 van de 2 RAM-sloten vrij, 32 GB geplaatst
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
- “Heeft meerdere” kan ook een array zijn. Het aantal sloten ligt vast, dus de lengte van de array is meteen het aantal sloten, en
nullis een leeg slot. Zie “Heeft meerdere”-relatie. - Omdat de array private is, kan niemand een vijfde latje in een bord met vier sloten duwen: alles loopt langs
PlaatsRam. - De processor en de grafische kaart komen binnen via een property, net als de harde schijf bij manier 3 in het boek. Daarom kan elk van beide
nullzijn, en controleertTestMoederborddat eerst.
Politiek (Essential)
Maak een programma dat de regering van een land simuleert, met de klassen Land, Minister en President.
Minister. Een minister heeft enkel een autoproperty Naam.
President. Een president is een minister, met één extra autoproperty Teller (int) die op 4 start en een private setter heeft. Elke aanroep van de methode JaarVerder verlaagt de teller met 1.
Land. Een land heeft 0 of 1 president, 0 of 1 eerste minister en 0 tot 4 andere ministers in een List<Minister>. Die drie instantievariabelen zijn private. Ze worden niet in Land aangemaakt maar komen binnen via MaakRegering: het is dus aggregatie. Land heeft deze publieke methoden:
MaakRegeringkrijgt een president en eenList<Minister>met 1 tot en met 5 ministers. De eerste minister in de lijst wordt de eerste minister van het land, de andere gaan in de eigen lijst van het land. Heeft het land al een president, dan toont de methodeGaat niet. Dit land heeft al een regering., en klopt het aantal ministers niet, danEen regering heeft 1 tot 5 ministers nodig.. In beide gevallen verandert er niets.JaarVerderroeptJaarVerderop bij de president, als er een is. Staat zijn teller daarna op 0, dan toont de methodeDe regering is afgelopen.: de president en de eerste minister wordennullen de lijst met ministers wordt leeggemaakt.ToonRegeringtoont wie er in de regering zit, ofEr is geen regering..
Testcode. Je code werkt als je exact deze uitvoer krijgt.
President tim = new President() { Naam = "Tim" };
List<Minister> ministers = new List<Minister>();
ministers.Add(new Minister() { Naam = "Bruno" });
ministers.Add(new Minister() { Naam = "Freya" });
ministers.Add(new Minister() { Naam = "Peter" });
ministers.Add(new Minister() { Naam = "Ann" });
Land mijnLand = new Land();
mijnLand.MaakRegering(tim, new List<Minister>());
mijnLand.MaakRegering(tim, ministers);
mijnLand.MaakRegering(tim, ministers);
mijnLand.ToonRegering();
for (int jaar = 1; jaar <= 4; jaar++)
{
Console.WriteLine($"Jaar {jaar}");
mijnLand.JaarVerder();
}
mijnLand.ToonRegering();Een regering heeft 1 tot 5 ministers nodig.
Gaat niet. Dit land heeft al een regering.
President: Tim
Eerste minister: Bruno
Ministers: Freya, Peter, Ann
Jaar 1
Jaar 2
Jaar 3
Jaar 4
De regering is afgelopen.
Er is geen regering.
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
Denkvraag. Stel dat je land geen president heeft maar een koning. Kan Koning dan ook van Minister erven?
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
Deel 2: verkiezingen. Maak een klasse VerkiezingsUitslag met twee autoproperties met een private setter: VerkozenPresident (een President) en VerkozenMinisters (een List<Minister>). De default constructor vult ze zelf: een nieuwe president en 5 nieuwe ministers, elk met een willekeurige naam.
Tip 1, willekeurige naam: schrijf in de klasse een
private string NaamGen()-methode die een string opbouwt met een willekeurige lengte (bv. tussen 5 en 10 tekens) waarbij elk teken een willekeurige kleine letter is (gebruik bv.(char)rng.Next('a', 'z' + 1)).Tip 2, één Random: declareer
Randomals static variabele op klasseniveau (private static Random rng = new Random();). Zo delen alle objecten van de klasse één generator, zoals bij deDobbelsteenin static en Random.
Nu is het opzetten van een regering in Main heel kort:
VerkiezingsUitslag uitslag = new VerkiezingsUitslag();
Land nieuwLand = new Land();
nieuwLand.MaakRegering(uitslag.VerkozenPresident, uitslag.VerkozenMinisters);
nieuwLand.ToonRegering();De namen zijn telkens anders, bijvoorbeeld:
President: nmqkikrrc
Eerste minister: aruqzpwbc
Ministers: vqfnu, dmtshabfgj, efenbn, rrxuqap
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
- Dezelfde ministers, bekeken vanuit twee klassen:
VerkiezingsUitslagmaakt ze zelf aan (compositie),Landkrijgt ze binnen viaMaakRegering(aggregatie). MaakRegeringneemt de ministers over in een eigen private lijst. Zo kanMainde regering niet meer veranderen via de lijst die het meegaf.- Controleer op
nullvoor je de president aanspreekt: een land zonder regering heeft er geen. Zie NullReferenceException is een klassieke fout.
Stevens bibliotheek (Essential)
Stagiair Steven moest een bibliotheek programmeren. Een bibliotheek heeft boeken en leden, en een lid kan een boek lenen. Een boek dat uitgeleend is, mag niet uit de bibliotheek verdwijnen. Steven vroeg het aan een A.I. en plakte alles in zijn project:
internal class Boek
{
public string Titel { get; private set; }
public bool IsUitgeleend { get; set; }
public Boek(string titel)
{
Titel = titel;
}
}internal class Lid : Boek
{
private Boek uitgeleend;
public string Naam { get; private set; }
public Lid(string naam)
{
Naam = naam;
}
public void Leen(Boek boek)
{
uitgeleend = boek;
boek.IsUitgeleend = true;
}
public override string ToString()
{
return $"{Naam} leest {uitgeleend.Titel}";
}
}internal class Bibliotheek
{
// private set: zo kan niemand van buitenaf nog aan de boeken
public List<Boek> Boeken { get; private set; } = new List<Boek>();
private List<Lid> leden = new List<Lid>();
public void VoegBoekToe(Boek boek)
{
Boeken.Add(boek);
}
public void VerwijderBoek(Boek boek)
{
if (boek.IsUitgeleend)
{
Console.WriteLine($"{boek.Titel} is uitgeleend en kan niet weg.");
}
else
{
Boeken.Remove(boek);
}
}
public void SchrijfIn(Lid lid)
{
leden.Add(lid);
}
public static void ToonAantalBoeken()
{
Console.WriteLine($"Er staan {this.Boeken.Count} boeken in de bibliotheek.");
}
public void ToonLeden()
{
foreach (Lid lid in leden)
{
Console.WriteLine(lid);
}
}
}In Main:
Bibliotheek bib = new Bibliotheek();
Boek avonden = new Boek("De Avonden");
bib.VoegBoekToe(avonden);
bib.VoegBoekToe(new Boek("Het Achterhuis"));
bib.VoegBoekToe(new Boek("Max Havelaar"));
Lid anna = new Lid("Anna");
Lid bram = new Lid("Bram");
bib.SchrijfIn(anna);
bib.SchrijfIn(bram);
anna.Leen(avonden);
// Test: een uitgeleend boek mag niet weg
bib.VerwijderBoek(avonden);
bib.Boeken.Remove(avonden);
Bibliotheek.ToonAantalBoeken();
bib.ToonLeden();Deel 1. Het project compileert niet: de compiler geeft twee foutmeldingen. De waarschuwing CS8618 over uitgeleend mag je laten staan. Bij welke lijnen horen de twee fouten, wat betekenen de meldingen, en hoe herstel je ze? Opgelet: bij één van de twee is de snelste oplossing niet de juiste.
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
Deel 2. Nu compileert het. Steven verwacht deze uitvoer, want geen van beide lijnen onder // Test mag het boek weghalen:
De Avonden is uitgeleend en kan niet weg.
Er staan 3 boeken in de bibliotheek.
Anna leest De Avonden
Bram heeft geen boek
Voer het programma uit. Er zitten nog twee fouten in die de compiler niet vindt. Zoek ze en herstel ze.
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
- De melding CS7036 wijst naar de constructor van
Lid, maar de fout zit in: Boek. Klopt de “is een”-zin niet, dan is het een “heeft een”. Zie Associatie of overerving? private setbeschermt de property, niet de lijst erachter. Zie Stagiair Steven.- Een instantievariabele van een eigen klasse blijft
nulltot er een object in komt. Met enkel Anna in de bibliotheek had Steven de crash niet gezien. Zie NullReferenceException is een klassieke fout. - In een
staticmethode bestaatthisniet. Zie Het this keyword.
Worldbuilding (Essential, GPT)
Je werkt een vereenvoudigde spelwereld voor een RPG uit. Een wereld bestaat uit zones, zoals een betoverd bos of een brandende woestijn. In de zones liggen voorwerpen: wapens, drankjes, schatten.
- Een wereld maakt en beheert zijn eigen zones: dat is compositie. Buiten de klasse
Wereldkrijgt niemand een zone in handen. - De voorwerpen bestaan ook los van een zone: een speler kan ze later meenemen, en ze kunnen naar een andere zone verhuizen. Dat is aggregatie.

Deel 1: Voorwerp. Een Voorwerp heeft een Naam, een Gewicht (double, in kg) en een Waarde (int, in goudstukken), alle drie via de constructor. ToString geeft Magisch zwaard (3,5 kg, 1200 goudstukken). De static methode VergelijkWaarde(Voorwerp voorwerp1, Voorwerp voorwerp2) toont welk van de twee meer waard is, of dat ze evenveel waard zijn.
Deel 2: Zone. Een Zone heeft een Naam en een Moeilijkheid (1 tot 10), via de constructor, en een private lijst met voorwerpen. Methoden:
VoegVoorwerpToe(Voorwerp voorwerp)enVerwijderVoorwerp(Voorwerp voorwerp).WaardevolleVoorwerpen(int minimum)geeft een nieuweList<Voorwerp>terug met de voorwerpen die minstens zoveel waard zijn.TotaalGewicht()geeft het gewicht van alle voorwerpen samen.ToonInfo()toont de zone en haar voorwerpen, zoals in de uitvoer hieronder.
Deel 3: Wereld. Een Wereld heeft een Naam en een MinimumLevel, via de constructor, en een private lijst met zones. Methoden:
VoegZoneToe(string naam, int moeilijkheid)maakt zelf een nieuwe zone aan en voegt ze toe.LegVoorwerp(string zoneNaam, Voorwerp voorwerp)legt een voorwerp in de zone met die naam, of toontDe zone ... bestaat niet..VerplaatsVoorwerp(Voorwerp voorwerp, string vanZone, string naarZone)haalt het voorwerp uit de ene zone en legt het in de andere.ZonesMoeilijkerDan(int moeilijkheid)geeft eenList<string>met de namen van de zones die moeilijker zijn.ToonWaardevolleVoorwerpen(int minimum)toont per zone de voorwerpen van minstens die waarde. Ze gebruiktWaardevolleVoorwerpenvan elke zone.MagBinnen(int level)geefttrueals een speler met dat level de wereld binnen mag.ToonInfo()toont de wereld, en laat elke zone daarna zichzelf tonen.
Tip: drie methoden zoeken een zone op naam. Schrijf daarvoor één private methode die de zone teruggeeft, of null als ze niet bestaat.
Testcode. Je code werkt als je exact deze uitvoer krijgt.
Wereld mystica = new Wereld("Mystica", 10);
mystica.VoegZoneToe("Betoverd bos", 5);
mystica.VoegZoneToe("Brandende woestijn", 8);
mystica.VoegZoneToe("Bevroren meer", 7);
Voorwerp zwaard = new Voorwerp("Magisch zwaard", 3.5, 1200);
Voorwerp drankje = new Voorwerp("Helend drankje", 0.5, 150);
Voorwerp mantel = new Voorwerp("Zandmantel", 1.2, 300);
mystica.LegVoorwerp("Betoverd bos", drankje);
mystica.LegVoorwerp("Brandende woestijn", zwaard);
mystica.LegVoorwerp("Brandende woestijn", mantel);
mystica.LegVoorwerp("Vulkaan", mantel);
mystica.ToonInfo();
Console.WriteLine("--- Zones moeilijker dan 6");
List<string> moeilijk = mystica.ZonesMoeilijkerDan(6);
foreach (string naam in moeilijk)
{
Console.WriteLine(naam);
}
Console.WriteLine("--- Voorwerpen van minstens 250 goudstukken");
mystica.ToonWaardevolleVoorwerpen(250);
Console.WriteLine("--- Vergelijk");
Voorwerp.VergelijkWaarde(zwaard, mantel);
Voorwerp.VergelijkWaarde(drankje, new Voorwerp("Rode appel", 0.2, 150));
Console.WriteLine("--- Het zwaard verhuist naar het bos");
mystica.VerplaatsVoorwerp(zwaard, "Brandende woestijn", "Betoverd bos");
mystica.ToonInfo();
Console.WriteLine("--- Wie mag binnen?");
Console.WriteLine(mystica.MagBinnen(8));
Console.WriteLine(mystica.MagBinnen(12));De zone Vulkaan bestaat niet.
Wereld Mystica (vanaf level 10)
Betoverd bos (moeilijkheid 5, 0,5 kg aan voorwerpen)
Helend drankje (0,5 kg, 150 goudstukken)
Brandende woestijn (moeilijkheid 8, 4,7 kg aan voorwerpen)
Magisch zwaard (3,5 kg, 1200 goudstukken)
Zandmantel (1,2 kg, 300 goudstukken)
Bevroren meer (moeilijkheid 7, 0 kg aan voorwerpen)
--- Zones moeilijker dan 6
Brandende woestijn
Bevroren meer
--- Voorwerpen van minstens 250 goudstukken
Magisch zwaard in Brandende woestijn
Zandmantel in Brandende woestijn
--- Vergelijk
Magisch zwaard is meer waard dan Zandmantel.
Helend drankje en Rode appel zijn evenveel waard.
--- Het zwaard verhuist naar het bos
Wereld Mystica (vanaf level 10)
Betoverd bos (moeilijkheid 5, 4 kg aan voorwerpen)
Helend drankje (0,5 kg, 150 goudstukken)
Magisch zwaard (3,5 kg, 1200 goudstukken)
Brandende woestijn (moeilijkheid 8, 1,2 kg aan voorwerpen)
Zandmantel (1,2 kg, 300 goudstukken)
Bevroren meer (moeilijkheid 7, 0 kg aan voorwerpen)
--- Wie mag binnen?
False
True
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
- Compositie in code:
VoegZoneToedoet zelfnew Zone(...), enMainkrijgt nooit een zone in handen. Daarom werktMainmet de namen van de zones, en geeftZonesMoeilijkerDannamen terug in plaats van zones. - Aggregatie in code: de voorwerpen worden in
Mainaangemaakt en komen binnen. Het zwaard verhuist naar het bos en blijft gewoon bestaan. ToonInfovan de wereld laat elke zone zichzelf tonen: elke klasse doet haar eigen werk.- Filteren doe je met een lus die een nieuwe lijst vult, niet met LINQ (
.Where()) (boeteblad).
Risk (Essential)
In het bordspel Risk verover je de wereld met legers die van land naar land trekken. Je maakt een vereenvoudigde versie met drie klassen.
Leger. Een leger heeft een Sterkte (int) die je via de constructor meegeeft. De sterkte is altijd positief: de setter werpt anders een ArgumentException op met de boodschap Een leger heeft een positieve sterkte.. Een leger weet ook waar het staat: een property Locatie van het type Land.
Land. Een land heeft een Naam, een private lijst met buurlanden en een private instantievariabele leger (null als er geen leger staat). Een property Leger met enkel een get geeft dat leger terug. Buurlanden en legers zijn aggregatie: verdwijnt een land, dan blijven zijn buren bestaan, en een leger kan gewoon naar een ander land trekken. Methoden:
VoegBuurToe(Land buur)enIsBuur(Land land).PlaatsLeger(Leger leger)zet het leger in het land. Het land wijst dan naar het leger, en het leger moet ook weten dat het in dit land staat. Gebruikthis, ook om de parameterlegeren de instantievariabelelegeruit elkaar te houden.VerwijderLeger()maakt het land leeg.ToStringgeeft bv.België (buurlanden: Nederland, Frankrijk, Duitsland), leger van 5, ofgeen legerop het einde.
Bordspel. Het bordspel heeft een private lijst met landen. De landen horen bij het spel en worden door het spel zelf aangemaakt: dat is compositie. Methoden:
VoegLandToe(string naam)maakt een nieuw land, voegt het toe aan de lijst en geeft het terug, zodat je er inMainmee kan spelen.MaakBuren(Land land1, Land land2)maakt van beide landen elkaars buur, zodat de kaart langs twee kanten klopt.ToonKaart()toont alle landen onder elkaar.VerplaatsLeger(Land van, Land naar)verplaatst het leger van het ene land naar het andere. Staat er invangeen leger, of isnaargeen buurland, dan werpt de methode eenExceptionop, zoals in de uitvoer hieronder. Staat er innaaral een leger, dan verdwijnt het verplaatste leger en krijgt dat andere leger zijn sterkte erbij.
Testcode. Je code werkt als je exact deze uitvoer krijgt.
Bordspel spel = new Bordspel();
Land belgie = spel.VoegLandToe("België");
Land nederland = spel.VoegLandToe("Nederland");
Land frankrijk = spel.VoegLandToe("Frankrijk");
Land duitsland = spel.VoegLandToe("Duitsland");
spel.MaakBuren(belgie, nederland);
spel.MaakBuren(belgie, frankrijk);
spel.MaakBuren(belgie, duitsland);
spel.MaakBuren(frankrijk, duitsland);
Leger blauw = new Leger(5);
belgie.PlaatsLeger(blauw);
frankrijk.PlaatsLeger(new Leger(3));
spel.ToonKaart();
Console.WriteLine("--- Blauw trekt naar Nederland");
spel.VerplaatsLeger(belgie, nederland);
Console.WriteLine($"Blauw staat in {blauw.Locatie.Naam}");
spel.ToonKaart();
Console.WriteLine("--- Frankrijk naar België, daarna naar Nederland");
spel.VerplaatsLeger(frankrijk, belgie);
spel.VerplaatsLeger(belgie, nederland);
spel.ToonKaart();
Console.WriteLine("--- Wat niet mag");
try
{
spel.VerplaatsLeger(frankrijk, duitsland);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
try
{
spel.VerplaatsLeger(nederland, frankrijk);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
try
{
Leger spookleger = new Leger(0);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}België (buurlanden: Nederland, Frankrijk, Duitsland), leger van 5
Nederland (buurlanden: België), geen leger
Frankrijk (buurlanden: België, Duitsland), leger van 3
Duitsland (buurlanden: België, Frankrijk), geen leger
--- Blauw trekt naar Nederland
Blauw staat in Nederland
België (buurlanden: Nederland, Frankrijk, Duitsland), geen leger
Nederland (buurlanden: België), leger van 5
Frankrijk (buurlanden: België, Duitsland), leger van 3
Duitsland (buurlanden: België, Frankrijk), geen leger
--- Frankrijk naar België, daarna naar Nederland
België (buurlanden: Nederland, Frankrijk, Duitsland), geen leger
Nederland (buurlanden: België), leger van 8
Frankrijk (buurlanden: België, Duitsland), geen leger
Duitsland (buurlanden: België, Frankrijk), geen leger
--- Wat niet mag
In Frankrijk staat geen leger.
Frankrijk is geen buurland van Nederland.
Een leger heeft een positieve sterkte.
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
- In
PlaatsLegerdoetthistwee dingen:this.legeris de instantievariabele en niet de parameter, enleger.Locatie = this;geeft het land zelf mee aan het leger. Zo kloppen beide kanten na elke verhuis. Zie Het this keyword. Bordspelmaakt zijn landen zelf aan: compositie. DatVoegLandToehet nieuwe land teruggeeft, verandert daar niets aan. Een leger komt binnen viaPlaatsLeger: aggregatie.- Een land zonder leger heeft
nullinleger. Controleer daarop voor je naar de sterkte vraagt.
De Online Coach (Final Essentials, GPT)
Je bouwt de backend van een app voor personal training. Sommige objecten zijn eigendom van een ander object (compositie), andere wijzen gewoon naar elkaar (aggregatie).
Deel 1: de oefeningen en het schema. Een Oefening heeft een Naam, een Spiergroep en een AantalSets, via de constructor. ToString geeft Squat (benen) - 4 sets.
Een TrainingSchema heeft een SchemaNaam (via de constructor) en een private lijst met oefeningen. VoegOefeningToe(Oefening oefening) voegt er een toe. ToonVolledigSchema() toont de naam van het schema en daaronder elke oefening.
De oefeningen komen uit een catalogus in Main, en dezelfde oefening mag in meerdere schema’s zitten: dat is aggregatie.
Deel 2: de sporter. Een Sporter heeft een Naam en een eigen TrainingSchema, in een private instantievariabele. Het schema hoort bij de sporter: dat is compositie. Dus:
- De constructor
Sporter(string naam, string schemaNaam)maakt zelf een nieuw, leeg schema aan. Zo zit een sporter nooit zonder schema. ZetNieuwSchema(string schemaNaam)vervangt het schema door een nieuw, leeg schema.VoegOefeningToe(Oefening oefening)voegt een oefening toe aan zijn schema.Train()toont... traint., laat het schema zichzelf tonen en toont daarnaLekker getraind!.
Deel 3: de coach. Een Coach heeft een Naam en een private lijst met sporters. De coach bezit zijn sporters niet: stopt hij, dan trainen zij gewoon verder. Dat is aggregatie.
VoegSporterToe(Sporter sporter)voegt een sporter toe aan de lijst.MotiveerIedereen()toont voor elke sporter[naam coach] roept: KOMAAN [naam sporter], nog eentje!.
Een sporter kiest zelf zijn coach: geef Sporter een methode KiesCoach(Coach coach) die de sporter zelf toevoegt aan de lijst van die coach.
Testcode. Je code werkt als je exact deze uitvoer krijgt. De laatste twee lijnen tonen het verschil met compositie: de coach stopt, en Lotte traint verder.
Oefening squat = new Oefening("Squat", "benen", 4);
Oefening deadlift = new Oefening("Deadlift", "rug", 3);
Oefening bench = new Oefening("Bench press", "borst", 4);
Sporter arnold = new Sporter("Arnold", "Full body");
arnold.VoegOefeningToe(squat);
arnold.VoegOefeningToe(deadlift);
Sporter lotte = new Sporter("Lotte", "Blokweek light");
lotte.VoegOefeningToe(squat);
lotte.VoegOefeningToe(bench);
Coach coleman = new Coach("Coleman");
arnold.KiesCoach(coleman);
lotte.KiesCoach(coleman);
coleman.MotiveerIedereen();
arnold.Train();
arnold.ZetNieuwSchema("Zomer cut");
arnold.VoegOefeningToe(bench);
arnold.Train();
coleman = null;
lotte.Train();Coleman roept: KOMAAN Arnold, nog eentje!
Coleman roept: KOMAAN Lotte, nog eentje!
Arnold traint.
Schema Full body:
Squat (benen) - 4 sets
Deadlift (rug) - 3 sets
Lekker getraind!
Arnold traint.
Schema Zomer cut:
Bench press (borst) - 4 sets
Lekker getraind!
Lotte traint.
Schema Blokweek light:
Squat (benen) - 4 sets
Bench press (borst) - 4 sets
Lekker getraind!
Deze oplossing is afgeschermd.
Studenten krijgen de sleutel van hun lesgever. Heb je de sleutel al eens op dit toestel
gebruikt, dan verschijnt de oplossing hier vanzelf.
- Het schema is compositie: enkel
Sporterdoetnew TrainingSchema(...), en niemand anders krijgt het in handen. Een nieuw schema vervangt het oude, dat met niemand gedeeld was. - Oefeningen en sporters zijn aggregatie: ze worden in
Mainaangemaakt, komen binnen via een methode en kunnen in meerdere lijsten zitten.coleman = null;verandert niets aan Lotte. coach.VoegSporterToe(this): de sporter geeft zichzelf mee. Zie Object geeft zichzelf mee als parameter.Trainlaat het schema zichzelf tonen, en het schema laat elke oefening zichzelf tonen viaToString.