Object Oriented Programming of korter OOP is een techniek afkomstig van higher level programmeertalen zoals Java, C#, VB.NET, ... en vindt zijn oorsprong bij Smalltalk die het eerst de term Object Oriented Programming introduceerde.
In recentere jaren heeft deze techniek echter ook zijn weg gevonden naar webscripting talen zoals Python, Ruby, Perl en zelfs PHP.
OOP streeft ernaar om een project zo structureel mogelijk op te bouwen in objecten. Dit heeft voor de programmeur het grote voordeel dat code vanaf nu in logische componenten wordt opgedeeld en veel makkelijker te hergebruiken is.
Om het concept van objecten te illustreren wordt meestal een voorwerp uit het dagelijks leven als voorbeeld gebruikt. Neem bijvoorbeeld een auto. De auto is het object en dit object heeft bepaalde properties of eigenschappen. Een eigenschap van de auto kan een band, een deur, een spiegel, de uitlaat of eender welk ander onderdeel van de auto zijn. Maar een auto heeft ook methoden. Een methode kan starten of remmen zijn.
Dus hebben we nu eigenlijk een object met properties en methoden. Zo zit een object in programmeertalen er ook uit. Een mail object heeft bijvoorbeeld als property de ontvanger, de verzender en het bericht en als methode versturen. Dit zijn natuurlijk erg vereenvoudigde voorbeelden en in de praktijk zal het er een stuk ingewikkelder aan toe gaan maar de basisprincipes zijn steeds hetzelfde. Bron van deze introductie.
Een belangrijk concept bij OOP is het Black-box principe waarbij we de afzonderlijke objecten en hun werking als kleine zwarte dozen gaan beschouwen. Neem het voorbeeld van de auto: deze is in de echte wereld ontwikkeld volgens het blackbox-principe. De werking van de auto kennen tot in het kleinste detail is niet nodig om met een auto te kunnen rijden. De auto biedt een aantal zaken aan de buitenwereld aan (het stuur, pedalen, het dashboard), wat we de interface noemen, die je kan gebruiken om de interne staat van de auto uit te lezen of te manipuleren. Stel je voor dat je moest weten hoe een auto volledig werkte voor je ermee op de baan kon.
Binnen OOP wordt dit blackbox-concept encapsulatie genoemd. Het doel van OOP is andere programmeurs (en jezelf) zoveel mogelijk af te schermen van de interne werking van je code. Vergelijk het met de methoden uit vorig semester: "if it works, it works" en dan hoef je niet in de code van de methode te gaan zien wat er juist gebeurt.
Een elementair aspect binnen OOP is het verschil beheersen tussen een klasse en een object.
Wanneer we meerdere objecten gebruiken van dezelfde soort dan kunnen we zeggen dat deze objecten allemaal deel uitmaken van een zelfde klasse.
Zo hebben we bijvoorbeeld de klasse van de auto's. De verschillende auto's die je op de straat ziet rijden zijn allemaal objecten van die klasse. De klasse zelf is een soort algemene beschrijving waaraan alle objecten van dat type moeten voldoen (bv: alle auto's hebben 4 banden, 1 motor en kunnen sneller en trager rijden).
Een klasse is een beschrijving en verzameling van dingen (objecten) met soortgelijke eigenschappen
Een individueel object is een instantie van een klasse
Steve Jobs, de oprichter van Apple, was een fervent fan van OOP. In een interview, way back, gaf hij volgende uitstekende uitlegbron:
Jeff Goodell: Would you explain, in simple terms, exactly what object-oriented software is?
Steve Jobs: Objects are like people. They’re living, breathing things that have knowledge inside them about how to do things and have memory inside them so they can remember things. And rather than interacting with them at a very low level, you interact with them at a very high level of abstraction, like we’re doing right here.
Here’s an example: If I’m your laundry object, you can give me your dirty clothes and send me a message that says, “Can you get my clothes laundered, please.” I happen to know where the best laundry place in San Francisco is. And I speak English, and I have dollars in my pockets. So I go out and hail a taxicab and tell the driver to take me to this place in San Francisco. I go get your clothes laundered, I jump back in the cab, I get back here. I give you your clean clothes and say, “Here are your clean clothes.”
You have no idea how I did that. You have no knowledge of the laundry place. Maybe you speak French, and you can’t even hail a taxi. You can’t pay for one, you don’t have dollars in your pocket. Yet, I knew how to do all of that. And you didn’t have to know any of it. All that complexity was hidden inside of me, and we were able to interact at a very high level of abstraction. That’s what objects are. They encapsulate complexity, and the interfaces to that complexity are high level.
En omdat het vloeken in de kerk is om Steve Jobs in een C# cursus aan het woord te laten, hier wat Microsoft-oprichter Bill Gates over OOP te zeggen had:
In C# kunnen we geen objecten aanmaken voor we een klasse hebben gedefinieerd dat de algemene eigenschappen (properties) en werking (methoden) beschrijft.
Een klasse heeft de volgende vorm:
Volgende code beschrijft de klasse auto in C#
Binnen het codeblock dat bij deze klasse hoort zullen we verderop dan de werking via properties en methoden beschrijven.
De optionele access modifier komen we later op terug.
Je kan "eender waar" een klasse aanmaken, maar het is een goede gewoonte om per klasse een apart bestand te gebruiken:
In de solution explorer, rechterklik op je project
Kies Add
Kies Class..
Geef een goede naam voor je klasse
De naam van je klasse moet voldoen aan de identifier regels die ook gelden voor het aanmaken van variabelen!
Je kan nu objecten aanmaken van de klasse die je hebt gedefinieerd. Je doet dit door eerst een variabele te definiëren en vervolgens een object te instantiëren met behulp van het new
keyword:
We hebben nu twee objecten aangemaakt van het type Auto.
Let goed op dat je dus op de juiste plekken dit alles doet (bekijk de onderstaande screenshot):
Klassen maak je aan als aparte files in je project
Objecten creëer je in je code op de plekken dat je deze nodig hebt, bijvoorbeeld in je Main
methode bij een Console-applicatie
We zullen nu enkele basisconcepten van klassen en objecten toelichten aan de hand van praktische voorbeelden.
Stel dat we een klasse willen maken die ons toelaat om objecten te maken die verschillende mensen voorstellen. We willen aan iedere mens kunnen vragen waar deze woont en die zal dat dan op het scherm tonen.
We maken een nieuwe klasse Mens
en maken een methode Praat
die iets op het scherm zet:
We zien twee nieuwe aspecten:
Het keyword static
komt bij een klasse niet aan te pas (of toch minder zoals we later zullen zien)
Voor de methode plaatsen we public
: dit leggen we zo meteen uit
Je kan nu elders objecten aanmaken en ieder object z'n methode Praat
aanroepen:
Er zal 2x Ik ben een mens!
op het scherm verschijnen. Waarbij telkens ieder object (joske
en alfons
) zelf verantwoordelijk ervoor waren dat dit gebeurde.
De access modifier geeft aan hoe zichtbaar een bepaald deel van de klasse is. Wanneer je niet wilt dat "van buitenuit" (bv objecten van je klasse in de Main) een bepaalde methode kan aangeroepen worden, dan dien je deze als private
in te stellen. Wil je dit net wel dat moet je er expliciet public
voor zetten.
Test in de voorgaande klasse eens wat gebeurt wanneer je public
verwijderd voor de methode. Inderdaad, je zal de methode Praat
niet meer op de objecten kunnen aanroepen.
De reden: wanneer je voor een methode (of klasse) niet expliciet public
zet, dan kan deze methode niet van uit alle andere klassen worden aangeroepen.
Test volgende klasse eens, kan je de methode VertelGeheim
vanuit de Main op joske
aanroepen?
Als je duidelijk wil maken dat bepaalde code niet van buitenaf aangeroepen kan worden, schrijf dan private
in plaats van public
. Als je geen van beide schrijft, zit je code ergens tussenin public
en private
(zie later). Als beginnende programmeur maak je er best een gewoonte van duidelijk te kiezen voor public
of private
.
Waarom zou je bepaalde zaken private
maken?
Stel dat we in de klasse extra (hulp)methoden willen gebruiken die enkel intern nodig zijn, dan doen we dit. Volgende voorbeeld toont hoe we in de methode Praat
de private methode VertelGeheim
gebruiken:
Als we nu elders een object laten praten als volgt:
Dan zal de uitvoer worden:
We maken onze klasse wat groter, we willen dat een object een leeftijd heeft die we kunnen verhogen via een methode VerjaardagVieren
(we hebben de methode VertelGeheim
even weggelaten):
Hier zien we een pak details die onze aandacht vereisen:
Ook variabelen zoals int leeftijd
mogen een access modifier krijgen in een klasse. Ook hier, als je niet expliciet public
zet wordt deze als private
beschouwd.
Ook al is leeftijd
private
alle methoden in de klasse kunnen hier aan. Het is enkel langs buiten dat bijvoorbeeld volgende code niet zal werken rachid.leeftijd = 34;
.
We kunnen iedere variabele een beginwaarde geven.
Ieder object zal z'n eigen leeftijd hebben.
Die laatste opmerking is een kernconcept van OOP: ieder object heeft z'n eigen interne staat die kan aangepast worden individueel van de andere objecten van hetzelfde type.
We zullen dit testen in volgende voorbeeld waarin we 2 objecten maken en enkel 1 ervan laten verjaren. Kijk wat er gebeurt:
Als je deze code zou uitvoeren zal je zien dat de leeftijd van Elvis verhoogt en niet die van Bono wanneer we VerjaardagVieren
aanroepen. Zoals het hoort!
Bekijk opnieuw het voorbeeld:
De eerste regel binnenin de klasse betekent dat een Mens
wordt aangemaakt met een leeftijd van 1 jaar. WE noemen dit de initiële waarde van de instantievariabele leeftijd
. Het is niet verplicht deze te voorzien. Als je niet aangeeft welke waarde een variabele krijgt (hier of in, zoals we iets verder zullen zien, de constructor), dan zal de instantievariabele een defaultwaarde krijgen die afhangt van zijn type.
In dit hoofdstuk bespreken we eerst waarom properties nodig zijn. Vervolgens bespreken we de 2 soorten properties die er bestaan:
Full properties
Auto properties
Properties (eigenschappen) zijn de C# manier om objecten hun interne staat in en uit te lezen. Ze zorgen voor een gecontroleerde toegang tot de interne structuur van je objecten.
Stel dat we volgende klasse hebben:
Een SithLord
heeft steeds een verborgen Sith Name en ook een hoeveelheid energie die hij nodig heeft om te strijden. Het is uit den boze dat we eenvoudige data fields (energy
en name
) public
maken. Zouden we dat wel doen dan kunnen externe objecten deze geheime informatie uitlezen!
We willen echter wel van buiten uit het energy-level van een SithLord
kunnen instellen. Maar ook hier hetzelfde probleem: wat als we de energy-level op -1000
instellen? Terwijl energy
nooit onder 0
mag gaan.
Properties lossen dit probleem op
Oldschool oplossing
Vroeger loste men voorgaande probleem op door Get-methoden te schrijven:
Je zal deze manier nog in veel andere talen tegenkomen. Wij prefereren properties zoals we nu zullen uitleggen.
Je zou dan kunnen doen:
Een full property ziet er als volgt uit:
Dankzij deze code kunnen we nu elders dit doen:
Vergelijk dit met de vorige alinea waar we dit met Get en Set methoden moesten doen. Deze property syntax is veel eenvoudiger in het gebruik.
We zullen de property nu stuk per stuk analyseren:
public int Energy
: een property is normaal public
. Vervolgens zeggen we wat voor type de property moet zijn en geven we het een naam. Indien je de property gaat gebruiken om een intern dataveld naar buiten beschikbaar te stellen, dan is het een goede gewoonte om dezelfde naam als dat veld te nemen maar nu met een hoofdletter. (dus Energy
i.p.v. energy
).
{ }: Vervolgens volgen 2 accolades waarbinnen we de werking van de property beschrijven.
get {}
: indien je wenst dat de property data naar buiten moet sturen, dan schrijven we de get-code. Binnen de accolades van de get schrijven we wat er naar buiten moet gestuurd worden. In dit geval return energy
maar dit mag even goed bijvoorbeeld return 4
of een hele reeks berekeningen zijn. Het element dat je returnt in de get code moet uiteraard van hetzelfde type zijn als waarmee je de property hebt gedefinieerd (int
in dit geval).
We kunnen nu van buitenaf toch de waarde van energy
uitlezen via de property en het get-gedeelte: Console.WriteLine(palpatine.Energy);
set{}: in het set-gedeelte schrijven we de code die we moeten hanteren indien men van buitenuit een waarde aan de property wenst te geven om zo een interne variabele aan te passen. De waarde die we van buitenuit krijgen (als een parameter zeg maar) zal altijd in een lokale variabele value
worden bewaard. Deze zal van het type van de property zijn. Vervolgens kunnen we value
toewijzen aan de interne variabele indien gewenst: energy=value
We kunnen vanaf nu van buitenaf waarden toewijzen aan de property en zo energy
vtoch bereiken: palpatine.Energy=50
.
Snel property schrijven
Visual Studio heeft een ingebouwde shortcut om snel een full property, inclusief een bijhorende private dataveld, te schrijven. Typ propfull
gevolgd door twee tabs!
De full property Energy
heeft nog steeds het probleem dat we negatieve waarden kunnen toewijzen (via de set
) die dan vervolgens zal toegewezen worden aan energy
.
Properties hebben echter de mogelijkheid om op te treden als wachters van en naar de interne staat van objecten.
We kunnen in de set
code extra controles inbouwen. Als volgt:
Enkel indien de toegewezen waarde groter of gelijk is aan 0 zal deze ook effectief aan energy
toegewezen worden. Volgende lijn zal dus geen effect hebben: Palpatine.Energy=-1;
We kunnen de code binnen set
(en get
) zo complex als we willen maken.
We zijn niet verplicht om zowel de get
en de set
code van een property te schrijven.
Write-only property
We kunnen dus enkel energy
een waarde geven, maar niet van buitenuit uitlezen.
We kunnen dus enkel energy
van buitenuit uitlezen, maar niet aanpassen.
Opgelet: het readonly
keyword heeft andere doelen en wordt NIET gebruikt in C# om een readonly property te maken
Read-only property met private set
Soms gebeurt het dat we van buitenuit enkel de gebruiker de property read-only willen maken. We willen echter intern (in de klasse zelf) nog steeds controleren dat er geen illegale waarden aan private datafields worden gegeven. Op dat moment definieren we een read-only property met een private setter:
Van buitenuit zal enkel code werken die deget
-van deze property aanroept: Console.WriteLine(palpatine.Energy);
. Code die de set
van buitenuit nodig heeft zal een fout geven zoals: palpatine.Energy=65
; ongeacht of deze geldig is of niet.
Nu goed opletten: indien we in het object de property willen gebruiken dan moeten we deze dus ook effectief aanroepen, anders omzeilen we hem als we rechtstreeks energy
instellen.
Kijk zelf naar volgende slechte code:
De nieuw toegevoegde methode ResetLord
willen we gebruiken om de lord z'n energy terug te verlagen. Door echter energy=-1
te schrijven geven we dus -1 rechtstreeks aan energy
. Nochtans is dit een illegale waarde. We moeten dus in de methode ook expliciet via de property gaan en dus schrijven:
Het is een goede gewoonte om zo vaak mogelijk via de properties je interne variabele aan te passen en niet rechtstreeks het dataveld zelf.
Read-only Get-omvormers
Je bent uiteraard niet verplicht om voor iedere interne variabele een bijhorende property te schrijven. Omgekeerd ook: mogelijk wil je extra properties hebben voor data die je 'on-the-fly' kan genereren.
Stel dat we volgende klasse hebben
We willen echter ook soms de volledige naam op het scherm tonen ("Voornaam + Achternaam"). Via een read-only property kan dit supereenvoudig:
Of nog eentje:
Nog een voorbeeldje:
Vaak gebruiken we dit soort read-only properties om data te transformeren. Stel bijvoorbeeld dat we volgende klasse hebben:
Automatische eigenschappen (autoproperties) in C# staan toe om eigenschappen (properties) die enkel een waarde uit een private variabele lezen en schrijven verkort voor te stellen.
Zo kan je eenvoudige de klasse Person herschrijven met behulp van autoproperties. De originele klasse:
De herschreven klasse met autoproperties (autoprops):
Beide klassen hebben exact dezelfde functionaliteit, echter de klasse aan de rechterzijde is aanzienlijk eenvoudig om te lezen en te typen.
Je mag autoproperties beginwaarden geven door de waarde achter de property te geven, als volgt:
Merk op dat je dit enkel kan doen indien er geen extra logica in de property aanwezig is. Stel dat je bij de setter van age wil controleren op een negatieve waarde, dan zal je dit zoals voorheen moeten schrijven en kan dit niet met een automatic property:
Voorgaande property kan dus NIET herschreven worden met een automatic property.
Je kan automatic properties ook gebruiken om bijvoorbeeld een read-only property te definiëren . Als volgt:
Originele klasse:
Met autoprops:
En andere manier die ook kan is als volgt:
De enige manier om FirstName een waarde te geven is via de constructor van de klasse. Alle andere manieren zal een error genereren.Meer info.
Als je in Visual Studio in je code prop
typt en vervolgens twee keer de tabtoets indrukt dan verschijnt al de nodige code voor een automatic property. Je hoeft dan enkel nog volgende zaken in orde te brengen:
Het type van de property
De naam van de property (identifier)
De toegankelijkheid van get/set (public, private, protected)
Via propg
krijg je aan autoproperty met private setter.
Een veel gestelde vraag bij beginnende OO-ontwikkelaars is: "Moet dit in een property of in een methode gestoken worden?"
De regel is eenvoudig:
Betreft het een actie, iets dat het object moet doen (tekst tonen, iets berekenen, etc) dan plaats je het in een methode
Betreft het een eigenschap die een bepaalde waarde heeft, dan gebruik je een property
Hier een iets meer uitgebreid PRO antwoord.
De .NET klasse DateTime
is de ideale manier om te leren werken met objecten. Het is een nuttige en toegankelijk klasse.
Grote delen van deze tekst komen van zetoode.com.
Er zijn 2 manieren om DateTime
objecten aan te maken:
Door aan de klasse de huidige datum en tijd te vragen via DateTime.Now
Door manueel de datum en tijd in te stellen via de constructor
Volgend voorbeeld toont hoe we een object kunnen maken dat de huidige datum tijd van het systeem bevat. Vervolgens printen we dit op het scherm:
Via de constructor kunnen we beginwaarden meegeven bij het maken van een nieuw object. Er zijn 11 manieren waarop dit kan zoals je hier kan zien.
Enkele voorbeelden:
Ieder DateTime
object dat je aanmaakt heeft en hoop nuttige methoden.
Deze methoden kan je gebruiken om een bepaalde aantal dagen, uren, minuten en zo voort aan je huidige object toe te voegen. Al deze methoden geven steeds een nieuw DateTime object terug dat je moet bewaren wil je er iets mee doen:
AddDays
AddHours
AddMilliseconds
AddMinutes
AddMonths
AddSeconds
AddTicks
AddYears
Een voorbeeld:
(voorgaande kan ook in 1 lijn: DateTime nextWeek= DateTime.Now.AddDays(7)
)
Uiteraard mag je ook een bestaand object overschrijven met het resultaat van deze methoden:
Properties zijn een zeer uniek aspect van C# zoals we in vorig hoofdstuk zagen. We zullen deze nog tot in den treuren leren maken. Via properties kan je de interne staat van objecten uitlezen én aanpassen, dit op een gecontroleerde manier.
Het fijne aan properties is dat :
je gebruikt ze alsof het gewone variabelen zijn
maar ze werken als methoden
Meer hierover later.
Enkele nuttige properties van DateTime
zijn:
Date
Day
DayOfWeek
DayOfYear
Hour
Millisecond
Minute
Month
Second
Ticks
TimeOfDay
Today
UtcNow
Year
Alle properties van DateTime zijn read-only.
Een voorbeeld:
Uiteraard mag je ook deze properties gebruiken om direct naar het scherm te schrijven:
Je hebt een invloed op hoe DateTime objecten naar string worden opgezet. Je kan dit door door extra formatter syntax mee te geven.
Dit zie je in volgende voorbeeld:
Wil je nog meer controle over de output dan kan je ook zelf je formaat specifieren.
De manier waarop DateTime
objecten worden getoond (via ToString) is afhankelijk van de landinstellingen van je systeem. Soms wil je echter op een andere manier dit tonen. Je doet dit door mee te geven volgens welke culture de tijd en datum getoond moet worden.
Dit vereist dat je eerst een CultureInfo
aanmaakt en dat je dan meegeeft:
Een lijst van alle cultures in .NET kan je hier terugvinden.
Opgelet, enkel indien een specifieke culture op je computer staat geïnstalleerd zal je deze kunnen gebruiken.
Sommige methoden zijn static
dat wil zeggen dat je ze enkel rechtstreeks op de klasse kunt aanroepen. Vaak zijn deze methoden hulpmethoden waar de individuele objecten niets aan hebben.
Parsen laat toe dat je strings omzet naar DateTime
. Dit is handig als je bijvoorbeeld de gebruiker via ReadLine
tijd en datum wilt laten invoeren:
Zoals je ziet roepen we Parse
aan op DateTime
en dus niet op een specifiek object.
Deze nuttige methode geeft een bool
terug om aan te geven het meegegeven object eens schrikkeljaar is of niet:
Je kan DateTime objecten ook bij mekaar optellen en aftrekken. Het resultaat van deze bewerking geeft echter NIET een DateTime object terug, maar een TimeSpan
object. Dit is een object dat dus aangeeft hoe groot het verschil is tussen de 2 DateTime objecten:
Maak een applicatie die bestaat uit een oneindige loop. De loop zal iedere seconde pauzeren: System.Threading.Thread.Sleep(1000);
. Vervolgens wordt het scherm leeg gemaakt en wordt de huidige tijd getoond. Merk op dat ENKEL de tijd wordt getoond, niet de datum.
Maak een applicatie die aan de gebruiker vraagt op welke dag hij jarig is. Toon vervolgens over hoeveel dagen z'n verjaardag dan zal zijn.
Code makkelijk toegankelijk maken
Vermijden heleboel piepkleine projectjes aan te maken
We gaan leren werken met grotere hoeveelheden code. We zullen voortaan niet meer al onze programma's in een apart project plaatsen, maar een keuzemenu gebruiken om daaruit alle andere programma's op te starten.
Wanneer de gebruiker de Main
van de klasse Program
opstart, krijg je een keuzemenuutje. Hierop worden omschrijvingen getoond voor alle oefeningen die je al hebt, gevolgd door de unieke titel van de oefening in kwestie. Wanneer de gebruiker het getal intypt dat overeenstemt met een oefening, wordt de oefening opgestart.
Voorbeeldoutput:
Wat wil je doen?
1. Vormen tekenen (h8-vormen)
2. Auto's laten rijden (h8-autos)
3. Patiënten tonen (h8-patienten)
4. Honden laten blaffen (h8-blaffende-honden)
Wanneer de gebruiker een van deze opties kiest door het juiste getal in te typen, wordt dat programma opgestart. Als hij iets intypt dat niet kan worden uitgevoerd, komt er een boodschap ongeldig getal!
. Wanneer je dit programma voor het eerst schrijft, kan je alleen nog maar ongeldige keuzes maken.
Doorloop de instructies en uitleg op ModernWays, maar let op volgende zaken:
We werken niet in een map voor het vak "Programmeren 3", maar in een map "OOP" (zoals de namespace die we hanteren, maar dat is geen regel die C# oplegt).
Indien je reeds een project met de naam OOP hebt, hoef je géén nieuw project aan te maken.
Je gebruikt ShapesBuilder.cs
in plaats van Vormen.cs
en schrijft in het algemeen je code in het Engels.
Je gebruikt de namespace OOP.Geometry
in plaats van Wiskunde.Meetkunde
.
Als je van stap 6 naar stap 7 gaat, laat je de code voor de eigenschap Color
staan.
Later zullen we deze code refactoren om nog meer gebruik te maken van objecten.
Kennismaking met OOP
We bouwen een simulatie van rijdende auto's. We voorzien deze van een kilometerteller, een huidige snelheid, een methode om de gaspedaal te simuleren en om de rem te simuleren.
We starten vanaf de klasse Auto
uit de cursus (maar noemen deze Car
).
We voegen eigenschappen Odometer
en Speed
toe, beide doubles
.
We zorgen dat de snelheid nooit onder de 0km/u kan gaan en nooit boven de 120km/u door de eigenschap aan te passen.
We schrijven klassikaal een methode Gas()
die de snelheid met 10km/u verhoogt en de auto verplaatst met zijn gemiddelde snelheid / 60 (om één minuut rijden te simuleren). De gemiddelde snelheid is het gemiddelde van de snelheid voor en na het verhogen.
We schrijven individueel een methode Brake
die gelijkaardig werkt, maar die de snelheid met 10 km/u verlaagt.
We schrijven een methode Main
die twee auto's aanmaakt
de eerste vijf keer laat versnellen, drie keer laat remmen
de tweede tien keer laat versnellen en een keer laat remmen
in onderstaand formaat de snelheid en afgelegde weg afprint: auto 1: km/u, afgelegde weg km auto 2: km/u, afgelegde weg km
Kennismaking met OOP
Kennismaking met refactoring
Toepassing van encapsulatie
We hebben al wat code, maar we vinden deze moeilijk te onderhouden omdat we allerlei variabelen moeten onderhouden. We refactoren deze om zo een meer objectgericht en beter onderhoudbaar programma te bekomen.
Introduceer een klasse Patient
Vervang alle arrays door één array van objecten van de klasse Patient
Zorg dat het afgeprinte verslag er identiek uitziet aan het oorspronkelijke verslag
Code om van te starten:
Kennismaking met OOP Kennismaking met refactoring
Toepassing van abstractie
We krijgen een programma dat al objecten bevat, maar dit programma moet zelf nog veel rekening houden met hoe deze objecten in elkaar zitten. We refactoren het om zo een meer objectgericht en beter onderhoudbaar programma te bekomen.
Je krijgt volgende twee files. De bestandsnamen volgen de afspraak:
en
Volg hierbij volgende stappen:
Maak de random generator statisch onderdeel van de klasse BarkingDog
.
Voeg volgende code toe binnen de klasse BarkingDog
:
git status -u
!Vanaf hier veronderstellen we dat je in één groot project werkt dat één klasse Program
heeft. De oefeningen worden los van elkaar omschreven, maar je zorgt ervoor dat ze getest kunnen worden via het keuzemenu in je klasse Program
.
Main
methodesIndien je meerdere klassen hebt met een methode Main
, moet je aangeven welke normaal gebruikt wordt voor de uitvoering van je programma. Dat doe je door aan je .csproj
-bestand het volgende toe te voegen: <StartupObject>Namespace-van-de-opstartklasse.Naam-van-de-opstartklasse</StartupObject>
Dit staat hier niet zomaar! Als je dit niet doet, zullen je oefeningen niet uitgevoerd kunnen worden. Je .csproj
file staat in dezelfde map als je .cs
-bestanden en indien het niet opent in Visual Studio, kan je het openen in Kladblok.
Bijvoorbeeld:
(Je file zou er al gelijkaardig moeten uitzien, maar je moet zelf het StartupObject
toevoegen.)
aanmaken van DateTime
objecten
formatteren van DateTime
objecten
We willen voor een willekeurige datum kunnen bepalen welke dag van de week het is.
je moet eerst de dag, maand en jaar opvragen en een DateTime
aanmaken
daarna moet je laten zien over welke dag van de week het gaat
gebruik hiervoor formattering van een DateTime
laat ook de datum zelf zien in een formaat dat leesbaar is voor de gebruiker
als je computer niet volledig ingesteld is op Belgisch Nederlands, kan het resultaat er wat anders uitzien.
noem de klasse waarin je dit schrijft DayOfWeekProgram
schrijf je code in de statische methode Main
roep de statische Main
van DayOfWeekProgram
op in het keuzemenu van Program
aanmaken van DateTime
objecten
We willen weten hoe veel fracties van een seconde al verlopen zijn sinds het begin van de jaren 2000.
.NET stelt deze fracties (1 / 10000 milliseconden) voor als "ticks"
We willen weten hoe veel ticks er voorbijgegaan zijn sinds het absolute begin van het jaar 2000
Noem de klasse waarin je dit schrijft Ticks2000Program
gebruik van een statische property
We willen bepalen hoe veel schrikkeljaren er zijn tussen 1800 en 2020.
implementeer zelf een logica voor schrikkeljaren, maar laat dit over aan de klassen DateTime
maak gebruik van een statische methode van deze klasse
noem je klasse LeapYearProgram
en voorzie ze van een Main
eenvoudig code leren timen
gebruiken van DateTime
herhaling arrays
We zijn benieuwd hoe lang het duurt een array van 1 miljoen int
s te maken en op te vullen met de waarden 1,2,...
Bepaal het tijdstp voor en na aanmaken van de array.
Vul de array in met een for
-lus.
Noem de klasse waarin je dit schrijft ArrayTimerProgram
werken met klassen en objecten
gebruik maken van simpele properties en methodes
Dit programma geeft op basis van de input van een percentage de graad weer die je met dit gegeven zou behaald hebben.
Ontwerp een klasse ResultV1
die je zal tonen wat je graad is gegeven een bepaald behaald percentage. Het enige dat je aan een ResultV1
-object moet kunnen geven is het behaalde percentage. Enkel het totaal behaalde percentage wordt bijgehouden. Via een methode PrintHonors
kan de behaalde graad worden weergegeven. Dit zijn de mogelijkheden:
< 50: niet geslaagd;
tussen 50 en 68: voldoende;
tussen 68 en 75: onderscheiding;
tussen 75 en 85: grote onderscheiding;
> 85: grootste onderscheiding.
Je hoeft voorlopig geen rekening te houden met ongeldige waarden. Test je klasse door ResultV1
ook van een statische methode Main
te voorzien, waarin je enkele objecten van deze klasse aanmaakt en de verschillende properties waarden te geeft en vervolgens PrintHonors
oproept.
werken met klassen en objecten
gebruik maken van simpele properties en methodes
Dit programma geeft op basis van de input van een percentage de graad weer die je met dit gegeven zou behaald hebben.
Ontwerp een klasse ResultV2
die je zal vertellen wat je graad is gegeven een bepaald behaald percentage. Het enige dat je aan een ResultV2
-object moet kunnen geven is het behaalde percentage. Enkel het totaal behaalde percentage wordt bijgehouden. Via een methode ComputeHonors
kan de behaalde graad worden teruggegeven. Dit werkt op dezelfde manier als in versie 1 van deze oefening, maar de verschillende graden worden voorgesteld met een Enum
, Honors
. De methode ComputeHonors
toont het resultaat niet, maar geeft een waarde van deze Enum
terug. Het is aan de Main
om deze waarde af te printen, zodat je kan zien of je code werkt.
Test je klasse op dezelfde manier als versie 1. De teruggegeven waarden van Honors
mag je in de Main
meegeven aan Console.WriteLine
.
werken met klassen en objecten
gebruik maken van properties
Dit programma geeft op basis van de input van twee getallen de som van beide getallen, het verschil, het product en de deling. In het laatste geval en indien er een deling door nul zou worden uitgevoerd, wordt dit woordelijk weergegeven.
Maak een eenvoudige klasse NumberCombination
. Deze klasse bevat 2 getallen (type int
). Er zijn 4 methoden, die allemaal een double
teruggeven:
Sum
: geeft som van beide getallen weer
Difference
: geeft verschil van beide getallen weer
Product
: geeft product van beide getallen weer
Quotient
: geeft deling van beide getallen weer. Print "Error"
naar de console indien je zou moeten delen door 0 en voer dan de deling uit. Wat er dan gebeurt, is niet belangrijk.
Gebruik full properties voor Number1
en Number2
en toon in je Main
aan dat je code werkt.
Volgende code zou namelijk onderstaande output moeten geven:
werken met klassen en objecten
gebruik maken van properties om geldige waarden af te dwingen
Dit programma maakt enkele rechthoeken en driehoeken met gegeven afmetingen (in meter) aan, berekent hun oppervlakte en toont deze info aan de gebruiker. De rechthoeken en driehoeken die worden aangemaakt, zijn al gecodeerd in het programma. De gebruiker hoeft dus niets anders te doen dan het programma te starten.
Er is een klasse Rectangle
met properties Width
en Height
en een klasse Triangle
met Base
en Height
. Je programma maakt de figuren die hierboven beschreven worden aan met waarde 1.0
voor elke afmeting en stelt daarna hun afmetingen in via de setters voor deze properties. De oppervlakte wordt bepaald in een read-only property, Surface
van het type double
.
Indien om het even welk van deze properties wordt ingesteld op 0
(of minder) wordt er een foutboodschap afgeprint en wordt de afmeting niet aangepast.
De wiskundige formule voor de oppervlakte van een driehoek is basis * hoogte / 2.
Schrijf de voorbeelden uit in de Main
van een extra klasse, FigureProgram
.
(Er worden twee rechthoeken en twee driehoeken aangemaakt. De afmetingen van de eerste rechthoek worden eerst op -1
en 0
ingesteld.
werken met klassen en objecten
gebruik maken van properties om geldige waarden af te dwingen
Dit programma vraagt om de naam en leeftijd van een student. Er moet ook worden meegeven in welke klasgroep de student is ingeschreven. De groepen zijn EA1
, EA2
en EB1
. Vervolgens worden de punten voor 3 vakken gevraagd, waarna het gemiddelde wordt teruggegeven.
Maak een nieuwe klasse Student
. Deze klasse heeft 6 properties. Leeftijd en de punten stel je voor met full properties. Een student kan nooit ouder zijn dan 120. Je kan ook nooit een cijfer boven 20 behalen. Over leeftijden en cijfers onder 0 hoef je je geen zorgen te maken, want de achterliggende variabelen zijn byte
s en die zijn altijd minstens 0.
Name (string)
Age (byte)
ClassGroup (maak hiervoor een enum
ClassGroups
)
MarkCommunication (byte)
MarkProgrammingPrinciples (byte)
MarkWebTech (byte)
Voeg aan de klasse een read-only property OverallMark
toe. Deze berekent het gemiddelde van de 3 punten als double
.
Voeg aan de klasse ook de methode ShowOverview()
toe. Deze methode zal een volledig rapport van de student tonen (inclusief het gemiddelde m.b.v. de OverallMark
-property).
Test je programma door enkele studenten aan te maken en in te stellen. Volgende statische methode Main
zet je in de klasse Student
.
werken met klassen en objecten
gebruik maken van properties om geldige waarden af te dwingen
Deze is gelijkaardig aan de vorige versie van het programma, maar gebruikt iets geavanceerdere technieken.
Maak een nieuwe versie van H8-RapportModule-V2, waarbij je een full property gebruikt voor het percentage. Zorg ervoor dat dit steeds tussen 0 en 100 ligt. Vervang ook ComputeHonors
door een read-only property, Honors
.