Skip to content

5. Klassen en objecten

Een klasse is de mal waaruit objecten worden gemaakt. Van een object wordt gezegd dat het een instantie van een klasse is.

  

5.1. Een Object-klasse


Programma (classes_01)


# -*- coding=utf-8 -*-

class Objet:
    """une classe Objet vide"""

# elke variabele kan per definitie attributen hebben
obj1=Objet()
obj1.attr1="un"
obj1.attr2=100
# geeft het object weer
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# wijzigt het object
obj1.attr2+=100
# geeft het object weer
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# wijst de referentie van object1 toe aan object2
obj2=obj1
# wijzigt obj2
obj2.attr2=0
# geeft beide objecten weer
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
print "objet2=[{0},{1}]".format(obj2.attr1,obj2.attr2)

Opmerkingen:

  • regel 4: een andere vorm van commentaar. Dit commentaar, voorafgegaan door drie "", kan zich over meerdere regels uitstrekken;
  • regels 3-4: een lege objectklasse;
  • regel 7: instantiatie van de klasse Objet;
  • regel 17: kopiëren van verwijzingen. De variabelen obj1 en obj2 zijn twee pointers (verwijzingen) naar hetzelfde object.

Resultaten

1
2
3
4
objet1=[un,100]
objet1=[un,200]
objet1=[un,0]
objet2=[un,0]

5.2. Een klasse Persoon


Programma (classes_02)


# -*- coding=utf-8 -*-

class Personne:
    # attributen van de klasse
    # niet gedeclareerd – kunnen dynamisch worden aangemaakt

    # methode
    def identite(self):
        # gebruikt a priori niet-bestaande attributen
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)

# ---------------------------------- main
# de attributen zijn openbaar en kunnen dynamisch worden aangemaakt
p=Personne()
p.prenom="Paul"
p.nom="Langevin"
p.age=48
# aanroep van een methode
print "personne={0}\n".format(p.identite())

Opmerkingen:

  • regels 3-10: een klasse met één methode;
  • regel 8: elke methode van een klasse moet als eerste parameter het object self hebben, dat het huidige object aanduidt.

Resultaten

personne=[Paul,Langevin,48]

5.3. De klasse Personne met een constructor


Programma (classes_03)


# -*- coding=utf-8 -*-

class Personne:
    
    # constructor
    def __init__(self,prenom,nom,age):
        self.prenom=prenom;
        self.nom=nom;
        self.age=age;

    # methode
    def identite(self):
        # gebruikt a priori niet-bestaande attributen
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)

# ---------------------------------- main
# een Personne-object
p=Personne("Paul","Langevin",48)
# aanroep van een methode
print "personne={0}\n".format(p.identite())

Opmerkingen:

  • regel 6: de constructor van een klasse heet __init__. Net als bij de andere methoden is de eerste parameter self;
  • regel 18: er wordt een object Personne aangemaakt met de constructor van de klasse.

Resultaten

personne=[Paul,Langevin,48]

5.4. De klasse Personne met validatiecontroles in de constructor


Programma (classes_04)


# -*- coding=utf-8 -*-

import re

# -------------------
# een eigen uitzonderingsklasse
class MyError(Exception):
    pass

class Personne:
    
    # constructor
    def __init__(self,prenom="x",nom="x",age=0):
         # de voornaam mag niet leeg zijn
        match=re.match(r"^\s*(\S+)\s*$",prenom)
        if not match:
            raise MyError("Le prenom ne peut etre vide")
        else:
            self.prenom=match.groups()[0]
        # de achternaam mag niet leeg zijn
        match=re.match(r"^\s*(\S+)\s*$",nom)
        if not match:
            raise MyError("Le nom ne peut etre vide")
        else:
            self.nom=match.groups()[0]
        # de leeftijd moet geldig zijn
        match=re.match(r"^\s*(\d+)\s*$",str(age))
        if not match:
            raise MyError("l'age doit etre un entier positif")
        else:
            self.age=match.groups()[0]

    def __str__(self):
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
      
# ---------------------------------- hand
# een object 'Persoon'
try:
    p=Personne("  Paul  ","  Langevin  ",48)
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur
# een ander Person-object
try:
    p=Personne("  xx  ","  yy  ","  zz")
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur
# een andere persoon
try:
    p=Personne()
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur

Opmerkingen:

  • regels 7-8: een klasse MyError die is afgeleid van de klasse Exception. Deze voegt geen functionaliteit toe aan de laatste. Ze is er alleen om een eigen uitzondering te hebben;
  • regel 13: de constructor heeft standaardwaarden voor zijn parameters. De bewerking p=Personne() is dus gelijk aan p=Personne("x","x",0);
  • regels 15-9: de parameter prenom wordt geanalyseerd. Deze mag niet leeg zijn. Als dat wel het geval is, wordt de uitzondering MyError met een foutmelding gegenereerd;
  • regels 21-25: idem voor de naam;
  • regels 27-31: controle van de leeftijd;
  • regels 33-34: de functie __str__ vervangt de methode die voorheen identite heette;
  • regels 38-42: een persoon instantiëren en vervolgens diens identiteit weergeven;
  • regel 39: instantiëren;
  • regel 40: weergave. De bewerking vraagt om de persoon p weer te geven in de vorm van een tekenreeks. De Python-interpreter roept dan automatisch de methode p.__str__() aan, indien deze bestaat. Deze methode vervult dezelfde rol als de methode toString() in Java of in de .NET-talen;
  • regels 41-42: afhandeling van een eventuele uitzondering van het type MyError. Geeft vervolgens het foutbericht weer dat bij de uitzondering hoort;
  • regels 44-48: idem voor een tweede persoon die met onjuiste parameters is geïnstantieerd;
  • regels 50-54: idem voor een derde persoon die met de standaardparameters is geïnstantieerd.

Resultaten

1
2
3
personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[x,x,0]

5.5. Toevoeging van een methode die als tweede constructor fungeert


Programma (classes_05)


# -*- coding=utf-8 -*-

import re

# -------------------
# een eigen uitzonderingsklasse
class MyError(Exception):
    pass

class Personne:
    # attributen van de klasse
    # niet gedeclareerd – kunnen dynamisch worden aangemaakt
    
    # constructor
    def __init__(self,prenom="x",nom="x",age=0):
         # de voornaam mag niet leeg zijn
        match=re.match(r"^\s*(\S+)\s*$",prenom)
        if not match:
            raise MyError("Le prenom ne peut etre vide")
        else:
            self.prenom=match.groups()[0]
        # de achternaam mag niet leeg zijn
        match=re.match(r"^\s*(\S+)\s*$",nom)
        if not match:
            raise MyError("Le nom ne peut etre vide")
        else:
            self.nom=match.groups()[0]
            # de leeftijd moet geldig zijn
        match=re.match(r"^\s*(\d+)\s*$",str(age))
        if not match:
            raise MyError("l'age doit etre un entier positif")
        else:
            self.age=match.groups()[0]

    def initWithPersonne(self,p):
        # initialiseert het huidige object met een persoon p
        self.__init__(p.prenom,p.nom,p.age)

    def __str__(self):
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
      
# ---------------------------------- main
# een Person-object
try:
    p0=Personne("  Paul  ","  Langevin  ",48)
    print "personne={0}".format(p0)
except MyError, erreur:
    print erreur
# een ander Person-object
try:
    p1=Personne("  xx  ","  yy  ","  zz")
    print "personne={0}".format(p1)
except MyError, erreur:
    print erreur
# een andere persoon
p2=Personne()
try:
    p2.initWithPersonne(p0)
    print "personne={0}".format(p2)
except MyError, erreur:
    print erreur

Opmerkingen:

  • het verschil met het vorige script zit in de regels 35-37. We hebben de methode initWithPersonne toegevoegd. Deze maakt gebruik van de constructor __init__. Het is niet mogelijk om, zoals in getypeerde talen, methoden met dezelfde naam te hebben die worden onderscheiden door de aard van hun parameters of hun resultaat. Het is dus niet mogelijk om meerdere constructors te hebben die het object op basis van verschillende parameters zouden construeren, in dit geval een object van het type Personne.

Resultaten

1
2
3
personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[Paul,Langevin,48]

5.6. Een lijst met Personne-objecten


Programma (classes_06)


# -*- coding=utf-8 -*-

class Personne:
    ...

# ---------------------------------- main
# aanmaken van een lijst met Personen-objecten
groupe=[Personne("Paul","Langevin",48), Personne("Sylvie","Lefur",70)]
# identiteit van deze personen
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

Opmerkingen:

  • regels 3-5: de reeds beschreven klasse Personne

Resultaten

groupe[0]=[Paul,Langevin,48]
groupe[1]=[Sylvie,Lefur,70]

5.7. Aanmaken van een klasse die is afgeleid van de klasse Persoon


Programma (classes_07)


# -*- coding=utf-8 -*-

import re

class Personne:
    ...

class Enseignant(Personne):
    def __init__(self,prenom="x",nom="x",age=0,discipline="x"):
        Personne.__init__(self,prenom,nom,age)
        self.discipline=discipline

    def __str__(self):
        return "[{0},{1},{2},{3}]".format(self.prenom,self.nom,self.age,self.discipline)
  

# ---------------------------------- hand
# aanmaken van een lijst met objecten 'Persoon' en afgeleiden
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70)]
# identiteit van deze personen
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

Opmerkingen:

  • regels 5-6: de reeds gedefinieerde klasse Personne;
  • regel 8: verklaart de klasse Enseignant als een afgeleide klasse van de klasse Personne;
  • regel 10: de constructor van de afgeleide klasse Enseignant moet de constructor van de bovenliggende klasse Personne aanroepen;
  • regels 21-22: om groep[i] weer te geven, gebruikt de interpreter de methode groep[i].__str__(). De gebruikte methode __str__() is die van de daadwerkelijke klasse van groep[i], zoals uit de onderstaande resultaten blijkt.

Resultaten

groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]

5.8. Aanmaken van een tweede klasse die is afgeleid van de klasse Personne


Programma (classes_08)


# -*- coding=utf-8 -*-

import re

class Personne:
    ...

class Enseignant(Personne):
    ...
  
class Etudiant(Personne):
    def __init__(self,prenom="x",nom="x",age=0,formation="x"):
        Personne.__init__(self,prenom,nom,age)
        self.formation=formation

    def __str__(self):
        return "[{0},{1},{2},{3}]".format(self.prenom,self.nom,self.age,self.formation)

# ---------------------------------- hand
# aanmaken van een lijst met objecten van het type 'Persoon' en afgeleiden
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70), Etudiant("Steve","Boer",22,"iup2 qualite")]
# identiteit van deze personen
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

Opmerkingen:

  • dit script is vergelijkbaar met het vorige.

Resultaten

groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]
groupe[2]=[Steve,Boer,22,iup2 qualite]