OOD Handboek

3Klassen, objecten en encapsulatie

Klasse = blauwdruk. Object = instantie, gemaakt met new. Een object combineert gegevens (attributen/properties) met gedrag (methodes). Encapsulation: velden private, toegang alleen via properties/methodes die de regels bewaken.

public class Bankrekening
{
    // veld (field): private, met underscore
    private decimal _saldo;

    // auto-property, alleen lezen van buiten
    public string Iban { get; }

    // property met private setter
    public string Eigenaar { get; private set; }

    // berekende (afgeleide) property: /IsRood in UML
    public bool IsRood => _saldo < 0;

    public static int Aantal { get; private set; }   // static: van de klasse
    private const decimal Limiet = -500m;            // constante

    public Bankrekening(string iban, string eigenaar)
    {
        if (string.IsNullOrWhiteSpace(iban))
            throw new ArgumentException("IBAN is verplicht.", nameof(iban));
        Iban = iban;
        Eigenaar = eigenaar;
        Aantal++;
    }

    public void Storten(decimal bedrag)
    {
        if (bedrag <= 0)
            throw new ArgumentOutOfRangeException(nameof(bedrag), "Moet positief zijn.");
        _saldo += bedrag;
    }

    public decimal GetSaldo() => _saldo;

    public override string ToString() => $"{Iban} ({Eigenaar}): € {_saldo:0.00}";
}
Uitleg

Encapsulation in de praktijk: het saldo is private en verandert alleen via Storten(), die ongeldige bedragen weigert. De constructor bewaakt dat een rekening nooit zonder IBAN bestaat. Aantal is static, dus gedeeld door alle rekeningen.

Functies en keywords
private set
Iedereen mag lezen, alleen de klasse zelf mag de waarde aanpassen.
nameof
Geeft de naam van een variabele of parameter als tekst, en blijft kloppen als je hem hernoemt.
string.IsNullOrWhiteSpace
true als de tekst null, leeg of alleen spaties is.
throw
Gooit een exception; de methode stopt direct en de fout gaat omhoog naar de aanroeper.
ArgumentException
Voor een ongeldig argument, zoals een lege tekst of verkeerde combinatie.
ArgumentOutOfRangeException
Voor een waarde buiten het toegestane bereik.
override
Vervangt een virtual of abstracte methode van de ouder; tijdens runtime wordt de versie van het echte object gekozen.
private
Alleen zichtbaar binnen deze klasse.
static
Hoort bij de klasse zelf, niet bij één object; gedeeld door alle objecten.
const
Vaste waarde die bij het compileren al vastligt en nooit verandert.
{ get; }
Alleen-lezen property; de waarde wordt in de constructor gezet.
=>
Korte schrijfwijze voor een methode of property die één expressie teruggeeft; in LINQ ook de pijl van een lambda.

#Property met validatie (volledige vorm)

private int _accuPercentage;
public int AccuPercentage
{
    get => _accuPercentage;
    set
    {
        if (value is < 0 or > 100)
            throw new ArgumentOutOfRangeException(nameof(value),
                "Accupercentage moet tussen 0 en 100 liggen.");
        _accuPercentage = value;
    }
}
// Zet in de constructor via de property (AccuPercentage = x;)
// zodat de validatie ook bij aanmaken draait!
Uitleg

Een volledige property met een eigen veld erachter. De setter controleert de waarde voordat hij wordt opgeslagen. Zet de beginwaarde in de constructor via de property en niet via het veld, anders sla je de controle over.

Functies en keywords
nameof
Geeft de naam van een variabele of parameter als tekst, en blijft kloppen als je hem hernoemt.
throw
Gooit een exception; de methode stopt direct en de fout gaat omhoog naar de aanroeper.
ArgumentOutOfRangeException
Voor een waarde buiten het toegestane bereik.
private
Alleen zichtbaar binnen deze klasse.
value
In een setter: de waarde die iemand probeert toe te kennen.
=>
Korte schrijfwijze voor een methode of property die één expressie teruggeeft; in LINQ ook de pijl van een lambda.
is
Controleert het type (of een patroon) en kan het object meteen in een nieuwe variabele zetten.

#Soorten properties

SchrijfwijzeLezenSchrijven
{ get; set; }iedereeniedereen
{ get; private set; }iedereenalleen de klasse
{ get; protected set; }iedereenklasse + subklassen
{ get; }iedereenalleen in constructor
{ get; init; }iedereenbij aanmaken: new X { R = 1 }
=> expressieiedereennooit (berekend)

#Access modifiers

ModifierWie mag erbij
publiciedereen
privatealleen deze klasse (standaard voor leden)
protecteddeze klasse + subklassen
internalhetzelfde project (standaard voor klassen)

#Constructor-ketens en object-initializer

public Persoon(string naam) : this(naam, 0) { }   // roept andere constructor aan
public Persoon(string naam, int leeftijd) { ... }

var c = new Circle { R = 1 };   // object initializer (init/set)
Uitleg

Met : this(...) roept de ene constructor de andere aan, zodat je de logica maar op één plek hebt. Met een object initializer ({ R = 1 }) vul je properties direct na het aanmaken; dat werkt voor properties met set of init.

Functies en keywords
this(...)
Roept een andere constructor van dezelfde klasse aan.
var
De compiler leidt het type zelf af uit de rechterkant.
Methode, constructor, destructor
Methode: functie binnen een klasse. Constructor: zelfde naam als de klasse, geen returntype, draait automatisch bij new. Destructor (~Klasse()): opruimen, in C# zelden nodig (garbage collector; voor bestanden gebruik je using). Object state = de huidige waarden van de velden van een object.