Als je een serieus programmeur bent of het serieus wil aan gaan pakken, zal je vroeg of laat te maken gaan krijgen met object georiënteerd programmeren. Deze vorm van software design neemt de laatste jaren erg toe en veel programmeurs zijn er erg enthousiast over. Met veel grote programmeertalen is object georiënteerd programmeren mogelijk, zoals Java, Python, C# en PHP. De afkorting van object georiënteerd programmeren is OOP (Object Oriented Programming), deze afkorting zal je ook tegenkomen in dit artikel. Om OOP goed te kunnen begrijpen, heb je wel basiskennis van programmeren nodig. Ook zou het handig zijn om enigszins basiskennis van Java te hebben. Lees snel verder om erachter te komen wat object georiënteerd programmeren is, hoe je het kan toepassen in Java en wat de beste manieren zijn om het te leren.
Ja, ik wil object georiënteerd leren programmeren op een heel gaaf en leerzaam platform!
Wat is object georiënteerd programmeren?
Object georiënteerd programmeren is een vorm van software design waarbij veel gebruikt gemaakt wordt van objecten, zoals je al kan begrijpen uit de term. Doordat de code is onderverdeeld in objecten, is de herbruikbaarheid van de code beter en het is makkelijker te onderhouden. Objecten bevatten variabelen (Eigenschappen van object) en functions (Gedrag). De functions in een object hebben vaak toegang tot de variabelen, ook wel fields genoemd, en kunnen deze vaak ook manipuleren. In een programmeertaal als Java worden functions ook wel methods genoemd. Later in het artikel zal je het woord “method” tegenkomen, maar dit is gewoon hetzelfde als een function.
Doordat er in object georiënteerd programmeren vaste regels en structuren zijn, weten de programmeurs met ervaring in OOP vaak waar ze aan toe zijn. Het instromen in een bestaand project is makkelijker en de samenwerking in een nieuw project zal soepeler verlopen, als iedereen zich aan de regels van OOP houdt. Hierbij praten we over de samenwerking op technisch gebied.
Class (Klasse)
Zonder classes kunnen er geen objecten gemaakt worden. Een class is een blauwdruk voor objecten. In een class staan variabelen en methods. Alle objecten die gecreëerd worden op basis van deze class, kunnen gebruik maken van de variabelen en methods die in de class zijn opgesteld. Een eenvoudige class bevat het volgende:
- Een modifier. Dit heeft met de toegankelijkheid van de class, variabele/field of method te maken. Dit kan in Java public, private, protected of default zijn. In Visibility, later in de tekst, vind je daar meer uitleg over.
- Een class naam.
- Een body. De body is omringd door {}.
- Een constructor.
Dit is een heel eenvoudige class. Een class kan bijvoorbeeld ook overerven van een parent class of bijvoorbeeld een interface implementeren. Hier krijg je ook meer uitleg over later in het artikel. Laten we eerst kijken hoe een eenvoudige class eruit ziet in Java:
public class Fiets { public String kleur; public Fiets() {} public void Bel(String geluid) { System.out.println(geluid); } }
public
= Is de modifier van de class.
public class Fiets
= Fiets is de naam van de class.
public Fiets()
= De constructor van de class.
public void Bel()
= Een method.
De naam van de class is vrij duidelijk. Een constructor heeft dezelfde naam als de class, alleen ook () achter de naam, omdat het een method is. Het is wel een aparte method, meer daarover in Constructor.
Visibility
We gaan de basis van visibility (Zichtbaarheid) bespreken. Het onderstaande is gericht op Java, net zoals alles in dit artikel. Maar in veel programmeertalen zijn de hoofdlijnen hetzelfde. Access modifiers zijn keywords waarmee de toegankelijkheid en zichtbaarheid van onder andere classes, variabelen en methods bepaald worden.
public = Is overal toegankelijk.
private = Is alleen in de eigen class toegankelijk.
protected = Is in de eigen package en child classes toegankelijk.
default = Is alleen binnen de eigen package beschikbaar.
Hieronder een voorbeeld waarin alles voorbij komt:
class Fiets { private String kleur; public Fiets() {} protected void Bel(String geluid) { System.out.println(geluid); } }
class Fiets
= Default. Deze class is alleen toegankelijk binnen de eigen package. De default access modifier heeft geen keyword, vandaar dat er niks voor class Fiets staat.
private String kleur
= De variabele/field kan alleen gebruikt worden in de eigen class.
public Fiets()
= De constructor is public en kan overal gebruikt worden.
protected void Bel(String geluid)
= De method is protected en kan alleen gebruikt worden binnen de eigen package en een child class.
Constructor
De constructor binnen een class is een aparte method. Het wordt gebruikt om objecten te initialiseren. Wanneer een object van een class is aangemaakt, wordt de constructor aangeroepen. Een constructor heeft dezelfde naam als de class. Let hierbij ook op de hoofdletter. Omdat het een method is, komt er ook () achter de naam van de constructor. Ook belangrijk om te weten is dat de constructor geen return type heeft. Net zoals “gewone” methods, heeft de constructor ook een body {}. Onderstaand zie je dat er een object wordt gemaakt van de class Fiets. Bij het aanmaken van het object komt ook gelijk de constructor in werking:
public class MyClass { public static void main(String args[]) { Fiets fiets1 = new Fiets(); } } class Fiets { private String kleur; public Fiets() { System.out.println("Fiets object is aangemaakt!"); } protected void Bel(String geluid) { System.out.println(geluid); } }
Bij het uitvoeren van de bovenstaande code is het resultaat: Fiets object is aangemaakt! Dit kan je op JDoodle uitproberen. In de code zie je twee classes, namelijk MyClass
en Fiets
. In MyClass
staat de main()
method. Deze method wordt als eerste aangeroepen, wanneer het programma wordt uitgevoerd. In de main()
method is een nieuw object aangemaakt in regel 4. Let daarbij op de volgende dingen:
Fiets
= Is de naam van de class waarvan het object is aangemaakt.
fiets1
= Is de naam van het object.
new Fiets()
= Gebruik het keyword “new” om een object aan te maken, gevolgd door de class naam en (). De constructor wordt hierdoor ook gelijk aangeroepen, zoals bij elk object.
Object
In onze echte wereld zijn veel objecten, zoals een boom, mens, kat, fiets en een auto. Als je de software objecten vergelijkt met de objecten in onze echte wereld, zijn er veel overeenkomsten. Software objecten hebben ook eigenschappen en gedrag. Als voorbeeld nemen we een kat. Een kat heeft bijvoorbeeld als eigenschappen: Kleur, naam en geslacht. Voorbeelden van gedrag zijn: Rennen, klimmen, springen, krabben en miauwen. De eigenschappen zijn de variabelen en de methods komen overeen met gedrag.
De code bovenstaand in Constructor in regel 4 laat zien hoe je een object aanmaakt. In de bovenstaande constructor zijn er geen parameters opgesteld en daarom hoef je geen arguments mee te geven. Als de constructor wel parameters heeft, is het verplicht om arguments mee te geven bij het aanmaken van het object. Anders kan de constructor niet uitgevoerd worden.
Ja, ik wil object georiënteerd leren programmeren op een heel gaaf en leerzaam platform!
OOP principes
OOP heeft een aantal vaste principes. De belangrijkste principes gaan we hieronder in theorie behandelen en er zijn ook codevoorbeelden te zien.
Encapsulation (Inkapseling)
Encapsulation voorkomt dat data makkelijk te manipuleren is buiten de class. Soms wil je niet dat iedereen data buiten een class makkelijk kan manipuleren en dan is encapsulation heel handig. Encapsulation ziet er zo uit in Java:
public class MyClass { public static void main(String args[]) { Fiets fiets1 = new Fiets(); fiets1.setKleur("Groen"); fiets1.setMerk("Gazelle"); System.out.println("Kleur van de fiets: " + fiets1.getKleur()); System.out.println("Merk van de fiets: " + fiets1.getMerk()); } } class Fiets { private String kleur; private String merk; public String getKleur() { return kleur; } public String getMerk() { return merk; } public void setKleur(String kleur) { this.kleur = kleur; } public void setMerk(String merk) { this.merk = merk; } }
In de class Fiets staan twee variabelen (fields), namelijk kleur
en merk
. Deze variabelen zijn allebei private en alleen bereikbaar in de eigen class. Buiten de class Fiets
zijn de variabelen niet bereikbaar en te manipuleren. Wel zijn deze variabelen bereikbaar en te manipuleren door de public getters en setters. Dit zijn methods die je herkent aan de “get” of “set” vooraan in de method naam. Met de public getters kan je zowel in, als buiten de class de waarde van de variabele ophalen. Met de public setters kan je een waarde geven aan de variabele, zowel in, als buiten de class. Bij de setters zie je ook een parameter. Bij het aanroepen van de method met een object geef je een argument mee. Zoals fiets1.setKleur("Groen");
In de body van de setter wordt de waarde van het argument meegegeven aan de variabele. this
verwijst naar de variabele van de class. kleur
zonder this
ervoor in de body van fiets1.setKleur(String kleur)
verwijst naar het argument.
Encapsulation zorgt voor meer flexibiliteit. Je kan er bijvoorbeeld ook voor kiezen om bepaalde variabelen alleen “leesbaar” te maken en niet de mogelijkheid geven om het te manipuleren. Dan maak je alleen een getter en laat je de setter weg. De gebruiker hoeft door encapsulation geen weet te hebben van de totale werking van de class. Met een setter kan je eenvoudig een waarde geven aan een variabele en met een getter haal je de waarde op. Meer hoef je niet te weten als je een waarde wil ophalen en/of manipuleren. Tevens is het goed voor de herbruikbaarheid. In Java worden ook vaak unit testen gebruikt. Encapsulation code is goed geschikt voor unit testen. Bij object georiënteerd programmeren is het belangrijk dat je encapsulation goed begrijpt.
Inheritance (Overerving)
Het woord inheritance (overerving) zegt het eigenlijk al. Een class die overerft van een parent class neemt bepaalde variabelen (Eigenschappen) en methods (Gedrag) over van de parent class. Stel dat je een zoontje of dochtertje krijgt. Dan zal je kind altijd bepaalde eigenschappen en gedrag gaan overnemen van jou. Object georiënteerd programmeren is erg gebaseerd op de werkelijkheid. Bij inheritance zie je dit goed terug. Hier een voorbeeld van inheritance in Java:
public class MyClass { public static void main(String args[]) { Gazelle gazelle = new Gazelle(); gazelle.Bel("Tring Tring Tring"); } } class Fiets { public String kleur; public Fiets() {} public void Bel(String geluid) { System.out.println(geluid); } } class Gazelle extends Fiets { public Gazelle() { System.out.println("Gazelle object is aangemaakt!"); } }
In de bovenstaande code zie je dat Gazelle
overerft van Fiets
. De Fiets
class bevat eigenschappen en gedrag die elke fiets zou moeten hebben. In dit geval gaan we er van uit dat elke fiets een kleur en een bel heeft. Gazelle is een bepaald merk voor een fiets. Gazelle is ook gewoon een fiets en hoort de eigenschappen en soorten gedrag van een fiets te hebben. Doordat Gazelle
overerft van Fiets
, heeft een Gazelle
ook een kleur en een bel. In de Gazelle
class zie je de variabele en method niet terugkomen, maar door de overerving neemt het deze automatisch over van de parent class. In regel 4 zie je dat er een gazelle
object wordt aangemaakt, gebaseerd op de Gazelle
class. In regel 5 roept het gazelle
object een method aan die in de parent class Fiets
staat. Dit kan alleen doordat er sprake is van overerving. Doordat er een parameter in de Bel(String geluid)
method staat, kan elk object die overerft van Fiets
en deze method overneemt, een eigen geluid produceren. In dit geval produceert een bel van een Gazelle fiets “Tring Tring Tring” als geluid. Zonder parameter kan elk object die overerft van Fiets
ook een eigen geluid produceren. Dit kan onder andere door middel van overriding. Meer daarover in Polymorphism.
Inheritance is erg goed voor de herbruikbaarheid van de code. Je hoeft niet steeds dezelfde variabelen en methods aan te maken, als je een nieuwe class aanmaakt. Je kan gewoon gebruik maken van de variabelen en methods uit de parent class. Let daarbij wel op de access modifiers.
Abstraction (Abstractie)
Een aantal classes hebben soms dezelfde variabelen en methods nodig, maar met een andere implementatie. In dit geval zou het handig zijn om in een abstracte class of interface alleen de methods zelf te definieren, zonder implementatie. De classes die gebruik maken van de abstracte class of interface kunnen het dan zelf implementeren. Hier een voorbeeld in Java:
public class MyClass { public static void main(String args[]) { Gazelle gazelle = new Gazelle(); gazelle.Bel(); } } abstract class Fiets { public abstract void Bel(); } class Gazelle extends Fiets { public void Bel() { System.out.println("Tring!"); } }
In de bovenstaande code zie je een abstracte class Fiets
met een abstracte method Bel()
. De Gazelle
class erft over van de abstracte class Fiets
. De method Bel()
is abstract in Fiets
en daarom is het in de Gazelle
class verplicht om een implementatie te geven aan de method. Als je de method Bel()
niet gebruikt in Gazelle
, terwijl het overerft van de abstracte class Fiets
, zal je een foutmelding krijgen. In Java kan je een method alleen abstract maken in een abstracte class. Als de method niet abstract zou zijn, is het niet verplicht om een implementatie te geven in de child class (Gazelle). Ook zou je een interface kunnen maken. Een interface kan je alleen maar implementeren, een class kan niet overerven van een interface. Van een abstracte class en een interface kan geen object gemaakt worden.
Abstraction is ook een belangrijk onderdeel in object georiënteerd programmeren. Het helpt om herhaling in code tegen te gaan. Het geeft classes verplichtingen mee om bepaalde methods te implementeren. Dit geeft duidelijkheid. Het geeft programmeurs flexibiliteit om een eigen implementatie te geven.
Ja, ik wil object georiënteerd leren programmeren op een heel gaaf en leerzaam platform!
Polymorphism (Polymorfisme)
Polymorphism betekent ook wel veelvormigheid. In het voorbeeld van Inheritance hebben we kunnen zien dat een class variabelen en methods kan overnemen van een andere class door overerving. Stel dat de child classes (Classes die overerven van parent class) allemaal dezelfde method hebben als de parent class, maar met een verschillende implementatie. Dan heb je allemaal verschillende uitkomsten bij het aanmaken een object van de parent en child classes, waarbij dezelfde method wordt aangeroepen. Laten we gaan kijken naar een voorbeeld in Java:
public class MyClass { public static void main(String args[]) { Fiets fiets = new Fiets(); Gazelle gazelle = new Gazelle(); Batavus batavus = new Batavus(); fiets.Bel(); gazelle.Bel(); batavus.Bel(); } } class Fiets { public void Bel() { System.out.println("Dingeling!"); } } class Gazelle extends Fiets { public void Bel() { System.out.println("Tring!"); } } class Batavus extends Fiets { public void Bel() { System.out.println("Tuut!"); } }
In de bovenstaande code zie je dat Gazelle
en Batavus
overerven van Fiets
. Gazelle
en Batavus
hebben een andere implementatie van de Bel()
method dan Fiets
. In regel 4 t/m 6 worden er drie verschillende objecten gemaakt van alle classes. In regel 8 t/m 10 spreken alle objecten de Bel()
method aan. Elk object heeft een eigen Bel()
method en zal deze ook uitvoeren. Ondanks dat Gazelle
en Batavius
overerven van Fiets
en de Bel()
method in Fiets
een implementatie heeft, kunnen de child classes ook een eigen implementatie aan Bel()
geven. Dit wordt ook wel overriding genoemd. Als je deze code zou uitvoeren in JDoodle of bijvoorbeeld in Eclipse, dan zou je het bel geluid zien van alle classes.
Polymorphism is in object georiënteerd programmeren onmisbaar. Het is belangrijk om dit goed te begrijpen als je met object georiënteerd programmeren bezig bent. Het is goed voor de code herbruikbaarheid. Door polymorphism kan je variabelen en methods hergebruiken in een nieuwe class.
Voordelen van OOP
Object georiënteerd programmeren is erg in opkomst en brengt grote voordelen met zich mee. Hier vindt je een opsomming van de voordelen:
- Makkelijker om problemen op te lossen. Je kan veelal snel zien in welke class zich er een probleem voordoet en dit oplossen.
- Herbruikbaarheid van de code door inheritance.
- Veel flexibiliteit door polymorphism.
- Sneller code schrijven door herbruikbaarheid.
- Hogere productiviteit.
- Implementatie lijkt erg op scenario’s in het echte leven.
- Het biedt een duidelijke structuur aan programma’s.
Nadelen van OOP
Ondanks dat object georiënteerd programmeren veel voordelen heeft, zitten er ook nadelen aan. Alles heeft zijn voor- en nadelen. Hier een opsomming van de nadelen:
- Het is moeilijk om functionaliteit aan classes in libraries toe te voegen die je zelf niet beheert.
- OOP projecten vergen over het algemeen meer rekenkracht van de processor.
- Grote planning voor een project is vereist als je OOP wil toepassen. Ligt ook aan de grote van het project.
Object georiënteerd programmeren oefeningen in Java
Belangrijk is om zelf te oefenen met object georiënteerd programmeren. Door alleen maar te lezen en zelf niks te doen, zal je het niet goed in de vingers krijgen. Bovenstaand zijn er al voorbeelden te zien van OOP code. Probeer deze code allemaal te runnen op JDoodle of bijvoorbeeld in een IDE, zoals Eclipse. Zo kan je zien wat de uitkomsten zijn. Probeer de code ook te begrijpen. Pas wat dingen aan in de code en kijk wat deze veranderingen teweeg brengen als je het programma uitvoert.
Een stappenplan om meer over object georiënteerd programmeren te leren, zou op deze manier kunnen:
- Maak een class met variabelen en methods.
- Maak een object van deze class.
- Roep met het object een method aan.
- Maak een andere class en laat het overerven van de class die je eerder hebt gemaakt.
- Maak in de child class een method die hetzelfde is als in de parent class.
- Kijk naar de verschillen als je van beide classes een object aanmaakt en dezelfde method aanroept.
- Probeer ook encapsulation, abstraction en polymorphism toe te passen.
Dit is echter maar het begin van object georiënteerd programmeren. Om het echt beter in de vingers te krijgen en er dieper op in te gaan, is een cursus of training aan te raden.
Hoe kan ik het beste object georiënteerd programmeren leren?
Het beste is door vooral zelf aan de slag te gaan. Natuurlijk heb je ook voorbeelden nodig, zoals in dit artikel, om verder te kunnen. Dit artikel bespreekt alleen de basis van object georiënteerd programmeren. OOP gaat nog een stuk dieper. Een erg goede manier om object georiënteerd programmeren te leren in Java, is door een cursus te volgen.
Op Pluralsight staan de beste videocursussen om meer over object georiënteerd programmeren te leren. Niet alleen in Java, maar bijvoorbeeld ook in C#, JavaScript en Kotlin kan je met videocursussen op Pluralsight aan de slag met object georiënteerd programmeren.
Als beginner ga je het helemaal vanaf scratch leren. Sowieso is Pluralsight een heel gaaf en leerzaam platform, waar je ook meer kan leren over onder andere vele programmeertalen en de nieuwste technologieën.
In “Pluralsight review en ervaringen” lees je een uitgebreide review over het platform. Het is zelfs 10 dagen helemaal gratis uit te proberen! Je zal gegarandeerd veel over object georiënteerd programmeren gaan leren met de videocursussen van hoge kwaliteit.
Mocht je het artikel hebben gelezen en er nog niet veel van snappen, dan raad ik je aan om het nog eens terug te lezen. Verstandig kan ook zijn om eerst het e-book “Snelcursus Leren Programmeren” te lezen. Als je de basis van het programmeren al wel begrijpt, is Pluralsight echt een grote aanrader om meer over object georiënteerd programmeren te gaan leren. Succes!
Heb je nog vragen en/of opmerkingen? Laat dan hieronder een reactie achter of neem contact op.
Hallo Bas,
Ik had de code voor polymorphism letterlijk overgenomen in JDoodle, maar ik krijg de volgende foutmelding: “Illegal start of type public.void Bel();
Wat betekent die foutmelding?
groetjes,
Marianne
Hallo Bas,
Marianne nog een keer over die foutmelding.
Ik had een punt gezet tussen ‘public’ en ‘void’. Het was dus een syntax error.
Wat suf, he?
Maar ja, je leert hiervan zal ik maar zeggen, hahaha.
Rest me nog te zeggen dat ik jouw site een grote steun vind voor een beginner zoals ik. Ik ben er erg blij mee. Dankjewel!!!
groetjes,
Marianne
Hoi Marianne,
Goed dat je het hebt opgelost. Zo zie je maar weer, een klein foutje is zo gemaakt.
Mooi om te horen dat ProgrammeerPlaats een grote steun voor je is!
Gr. Bas
Vraagje van dezelde Marianne als in augustus. Inmiddels ben ik een bescheiden beetje vooruitgegaan voor het leren van Java. Het gaat langzaam, maar ik ben blij met ieder succesje dat ik boek, 🙂
Klopt het dat de klasse “Fiets” in het encapsulation voorbeeld een “inner class” is van de klasse “MyClass”?
Ik heb ergens gelezen over het begrip inner classes en dat die nuttig zijn voor overzichtelijkheid en onderhoud van code.
groetjes,
Marianne
Hoi Marianne,
Goed dat je nog steeds bezig bent en steeds stapjes maakt!
Class “Fiets” is in het encapsulation voorbeeld geen inner class van “MyClass”. Het zijn twee aparte classes. Wel wordt er in “MyClass” een object gemaakt van de class “Fiets”.
Inner classes zijn zeker handig voor de leesbaarheid en het onderhoud van code. Hier lees je er ook meer over: https://www.w3schools.com/java/java_inner_classes.asp
Gr. Bas
Hoi Bas,
Dankjewel voor de link.
Goh, weet je waarom ik dacht dat het een inner class was?
Er staat geen access modifier voor Fiets. In het voorbeeld van W3Schools is dat ook zo. Daarin staan class OuterClass {}, gevolgd door class InnerClass{} en daaronder dan nog public class Main{code}
Main heeft de access modifier wel: public.
Maar misschien moet ik er nog maar even mee wachten om me in geneste classes te verdiepen, 🙂
In ieder geval hartelijk dank voor je reactie!
groetjes,
Marianne
Hoi Marianne,
Een Java bestand kan maar één public class hebben. De naam van deze public class moet overeenkomen met de naam van het Java bestand. Als er meerdere public classes zijn in hetzelfde Java bestand, dan raakt de compiler in de war.
In de public class staat ook de main() method, die de compiler als eerste checkt.
Gr. Bas Dingemans
Ja, inderdaad kan er maar 1 public class zijn in een Java bestand. Dat had ik dan gelukkig goed begrepen.
Ik ben hartstikke blij met jouw voorbeelden. Ik heb Eclipse op mijn computer gezet en daar kan ik ze bewaren en soms waag ik me al eens aan een kleine variatie, 🙂
Hartelijke groetjes,
Marianne