Het is dan ook één van de allereerste doelstellingen in deze cursus om je daarmee vertrouwd te maken.
Objecten, klassen en methoden zijn al ter sprake gekomen in de vorige cursusonderdelen, misschien kwamen bepaalde begrippen nogal abstract over. Dit hoofdstuk heeft als bedoeling je volledig vertrouwd te maken met de principes van het objectgeoriënteerd programmeren.
Objectgeoriënteerd programmeren is in feite een techniek om als programmeur het verdeel en heers principe toe te passen. Het idee erachter is dat we kleine autonome stukken programmacode maken die we dan vanuit ander programmaonderdelen kunnen gebruiken. We moeten ons naderhand geen zorgen meer maken om de kleine programmaonderdelen.
Sleutelconcepten
| Concept | Beschrijving |
|---|---|
| Klasse | Vormt de blauwdruk voor een object. Een klasse is een element waarvan je objecten afleidt, in de klasse staat aangegeven hoe het object er zal 'uitzien', wat je met het object kan doen. Klassen zijn de bouwplannen van Java. |
| Object | Een object is een instantie van een klasse. Dit betekent dat een object aangemaakt werd aan de hand van de richtlijnen van een klasse. |
| Gegevensleden | De variabelen die onderdeel zijn van een klasse. Je gebruikt ze om gegevens op te slaan die je voor het object of de klasse gebruikt. |
| Methode | Een functionaliteit die in een klasse is ingebouwd. |
| Overerving | Klassen kunnen de functionaliteit van een andere klasse gebruiken en overnemen. Dit principe wordt overerving genoemd. |
Het is heel belangrijk in te zien dat zonder het gebruik van klassen programmeren in Java onmogelijk is. Wanneer je een toepassing maakt begin je eenvoudigweg met het maken van een klasse. Wanneer deze toepassing een applet is, dan ga je meteen de klasse java.applet.Applet gebruiken in je project...
Het is dan ook ten zeerste aan te raden niet te 'licht' om te springen met de voorbeelden in dit hoofdstuk van de cursus. De inhoud van de voorbeelden zal niet altijd 'spectaculair' zijn, maar er komen principes en technieken aan bod die voor het maken van nuttige toepassingen onontbeerlijk zijn.
Er zijn twee onderdelen bij de opbouw van een klasse: de klassendeclaratie en de klassendefinitie. De declaratie vertelt Java wat het dient te weten over de nieuwe klasse:
[toegang] class klassenaam [extends...] [implements...]
{
//klassendefinitie komt hier
}
De klassendefinitie zullen we nu stap voor stap leren kennen.
public class Meubel { public String meubeltekst = "Ik ben een meubelstuk"; public Meubel() { } }
Hier maken we een klasse aan met de naam Meubel.
De klasse Meubel bevat een String-instantievariabele meubeltekst met de waarde "Ik ben en meubelstuk"
Deze klasse kan nu een blauwdruk vormen voor objecten in een andere klasse:
public class Winkel { public Winkel() { } public static void main(String[] args) { Meubel kast = new Meubel(); System.out.println(kast.meubeltekst); } }
In de klasse Winkel kunnen we nu objecten aanmaken van het type Meubel. Dit doen we op dezelfde manier als we vroeger met bvb. arrays en Strings hebben gewerkt.
We noemen meubeltekst een instantie-variabele daar we voor elk object van het type Meubel dat we straks aanmaken de waarde voor deze variabele apart kunnen instellen. M.a.w. elke instantie van de klasse Meubel zal over zijn eigen variabele meubeltekst beschikken.
public class Winkel {
public Winkel() {
}
public static void main(String[] args) {
Meubel kast = new Meubel();
Meubel stoel = new Meubel();
stoel.meubeltekst = "Ik ben een stoel !";
System.out.println(kast.meubeltekst);
System.out.println(stoel.meubeltekst);
System.out.println(kast.meubeltekst);
}
}
Compileren doe je vanaf de prompt met: javac naamklasse.java
Uitvoeren van consoleapplicaties doe je met de opdracht java naamklasse
Zorg ervoor dat de bestanden in eenzelfde map terechtkomen (of pas de CLASSPATH-variabele aan).
Zorg ervoor dat je eerst de benodigde klassen compileert voor je het hoofdprogramma compileert, dus eerst Meubel.java en dan Winkel.java compileren. Het enige programma dat je kan uitvoeren is dan Winkel. De toepassing Winkel gebruikt dan de klasse Meubel (achter de schermen).
Je merkt dat de instanties van de klasse Meubel (kast en stoel) de variabele meubeltekst binnen de klasse Meubel kunnen aanpassen.
De variabele meubeltekst is gedefiniëerd als public, daardoor is deze variabele toegankelijk van overal binnen het programma.
Mogelijke waarden voor de toegang tot een variabele zijn:
| Toegang | Beschrijving |
|---|---|
| public | toegankelijk van overal in het programma |
| private | enkel toegankelijk vanuit de klasse zelf |
| protected | toegankelijk binnen de klasse, binnen klassen van hetzelfde pakket en voor klassen afgeleid van die klasse |
In de toepassing Winkel hebben we een variabele meubeltekst gedefiniëerd. Deze variabele is een instantievariabele, elke instantie (object) dat afgeleid is van de klasse Winkel beschikt over zijn eigen variabele meubeltekst.
Wanneer je in een klasse waarden wenst vast te leggen die voor elke instantie hetzelfde zijn, maak je gebruik van klassevariabelen: deze variabelen zijn voor alle instanties van de klasse gelijk.
Klassevariabelen declareer je met het sleutelwoord static
Voorbeeld:
Toon volledige code...
Toon nieuwe code...
public class Meubel {
public static String meubeltekst = "Ik ben een meubelstuk";
public Meubel() {
}
}
public class Meubel {
public static String meubeltekst = "Ik ben een meubelstuk";
private static String slogan = ", de beste kwaliteit van het land";
static {
meubeltekst = meubeltekst.concat(slogan);
}
public Meubel() {
}
}
public class Winkel {
public Winkel() {
}
public static void main(String[] args) {
Meubel kast = new Meubel();
Meubel stoel = new Meubel();
System.out.println(kast.meubeltekst);
System.out.println(stoel.meubeltekst);
stoel.meubeltekst = "Ik ben een stoel !";
System.out.println(kast.meubeltekst);
System.out.println(stoel.meubeltekst);
}
}
Een methode is een codeblok waaraan de controle kan worden doorgegeven, de cod binnen dit blok wordt nu uitgevoerd.
In feite stellen methoden je in staat iets te doen met je klassen en objecten.
We hebben in voorgaande voorbeelden steeds gebruik gemaakt van een methode : System.out.println(). Deze methode zorgt er bij een console-applicatie voor dat tekst op het scherm wordt getoond.
Nu gaan we zelf methodes aanmaken binnen onze eigen klassen:
public class Meubel {
private static String meubeltekst = "Ik ben een meubelstuk";
public Meubel() {
}
public void toonTekst(){
System.out.println(meubeltekst);
}
}
public class Winkel {
public Winkel() {
}
public static void main(String[] args) {
Meubel kast = new Meubel();
Meubel stoel = new Meubel();
kast.toonTekst();
stoel.toonTekst();
}
}
De klassevariabele (static) meubeltekst werd als private gedeclareerd, we hebben dus geen toegang meer tot deze variabele vanuit code buiten de klasse Meubel.
In de klasse Meubel werd een methode toegevoegd met de naam toonTekst. Deze methode werd gedeclareerd als public, dit betekent dat de methode toonTekst wel toegankelijk is vanuit een andere klasse. Vanuit de klasse Winkel kunnen we deze methode toepassen op onze Meubel-objecten kast en stoel.
Toegang tot methodes:
| Toegang | Beschrijving |
|---|---|
| public | Toegankelijk vanuit elke plaats in het programma |
| private | Enkel toegankelijk vanuit de klasse waarin de methode is gedeclareerd |
| protected | Toegankelijk voor de huidige klasse, voor andere klassen in hetzelfde pakket en klassen die afgeleid zijn van de huidige klasse. |
Het gebruik van methoden schermt de variabelen van de klasse Meubel af. We zijn nu verplicht om de methode toonTekst te gebruiken om meubeltekst op het scherm te brengen. Deze werkwijze heeft als grote voordeel dat je nu binnen je methodes kan werken met controles. Deze techniek wordt wel eens data-encapsulation genoemd.
Doordat de variabele meubeltekst private is gedeclareerd, kunnen we de inhoud ervan niet meer rechtstreeks wijzigen buiten de klasse Meubel. Om toch toegang te hebben tot deze private variabele vanuit de klasse Winkel maken we in de klasse Meubel een publieke methode zetTekst aan.
Deze methode ontvangt een parameter, het is de bedoeling dat we bij het uitvoeren van de methode de meubeltekst kunnnen instellen op een zelf gekozen zin.
Toon volledige code...
Toon nieuwe code...
public class Meubel {
...
public void zetTekst(String nieuwemeubeltekst){
meubeltekst = nieuwemeubeltekst;
}
}
public class Winkel {
...
kast.zetTekst("Onze meubels zijn niet te overtreffen!");
...
}
}
Toon volledige code...
Toon nieuwe code...
public class Meubel {
...
public void zetTekst(String nieuwemeubeltekst){
meubeltekst = nieuwemeubeltekst;
}
public void toonPrijs(){
System.out.println(prijs);
}
public void zetPrijs(double nieuweprijs){
prijs = nieuweprijs;
}
}
public class Winkel {
...
kast.zetPrijs(200.99);
stoel.zetPrijs(50);
kast.toonTekst();
kast.toonPrijs();
stoel.toonPrijs();
}
}
Toon volledige code...
Toon nieuwe code...
public class Meubel {
...
public static void toonTekst(){
System.out.println(meubeltekst);
}
public static void zetTekst(String nieuwemeubeltekst){
meubeltekst = nieuwemeubeltekst;
}
...
}
public class Winkel {
...
Meubel.zetTekst("Onze meubels zijn niet te overtreffen");
...
Meubel.toonTekst();
kast.toonTekst();
...
}
}
Toon volledige code...
Toon nieuwe code...
public class Meubel {
...
public double berekenKortingsprijs( int korting){
return prijs - prijs * korting / 100;
}
}
public class Winkel {
...
System.out.println(kast.berekenKortingsprijs(20));
System.out.println(stoel.berekenKortingsprijs(50));
}
}
In het volgende onderdeel maak je kennis met speciale methoden genaamd constructors. Het is belangrijk hierbij op te merken dat gewone methoden net zoals contructors kunnen overloaded worden.
Constructors zijn codeblokken die worden uitgevoerd bij het aanmaken van een instantie (object) van een klasse. Je kan zelf constructors voor een klasse aanmaken op een eenvoudige manier: je voegt gewoon een methode toe aan de klasse met dezelfde naam als de klasse, zonder teruglevertype.
In het voorbeeld hieronder maken we twee constructors voor de klasse Meubel. We hebben twee methoden met de naam Meubel gedefiniëerd, deze hebben telkens andere parameters die worden ontvangen. Aan de hand van de opgegeven parameters weet Java welke constructor moet worden toegepast.
Het maken van meerdere constructors noemen we constructor-overloading. Ook gewone methodes kunnen overloaded worden. Je definiëert twee keer een methode met eenzelfde naam maar verschillende parameters (verschil qua type en/of qua aantal).
Toon volledige code...
Toon nieuwe code...
public class Meubel {
...
public Meubel() {
prijs = 0;
}
public Meubel(int nieuweprijs) {
prijs = nieuweprijs;
}
...
}
public class Winkel {
public Winkel() {
}
public static void main(String[] args) {
Meubel kast = new Meubel();
Meubel stoel = new Meubel(50);
Meubel.zetTekst("Onze meubels zijn niet te overtreffen");
kast.zetPrijs(200.99);
kast.toonPrijs();
stoel.toonPrijs();
}
}
...
public Meubel(int nieuweprijs) {
prijs = nieuweprijs;
}
...
Je kan met dezelfde naam als de variabele werken wanneer je in de constructor (of een andere methoden) gebruik maakt van het sleutelwoord this.
...
public Meubel(int prijs) {
this.prijs = prijs;
}
...
// NIET RECURSIEF !
public class Reken {
public static int berekenFaculteit(int getal) {
int fac = 1;
for(;getal>1;getal--){
fac = fac * getal;
}
return fac;
}
public static void main(String[] args) {
System.out.println(Reken.berekenFaculteit(6));
}
}
public class Reken2 {
public static int berekenFaculteit(int getal) {
if(getal == 1) {
return getal;
} else {
return getal * berekenFaculteit(getal-1);
}
}
public static void main(String[] args) {
System.out.println(Reken2.berekenFaculteit(5));
}
}
Java definiëert drie hoofdbereiken: klasse-niveau, methode-niveau en codeblok-niveau.
Voorbeeld:
public class Bereik {
int waarde; //waarde: zichtbaar in de volledige klasse
public Bereik(int nieuwewaarde) { // nieuwewaarde: enkel binnen deze methode
waarde = nieuwewaarde;
}
public void verhoog(){
int vergelijk = 10; //vergelijk: enkel binnen deze methode
if(waarde<vergelijk){
int verhoog = 20; //verhoog: enkel in dit if-blok
waarde += verhoog;
}
}
public static void main(String[] args) {
Bereik bereik1 = new Bereik(5);
bereik1.verhoog();
System.out.println(bereik1.waarde);
}
}
Toon volledige code...
Toon nieuwe code...
...
public class Winkel {
...
kast = null;
stoel = null;
}
}
Wanneer een object door de garbage-collector wordt opgehaald, gaat de garbage-collector een methode van het object met de naam finalize aanroepen, als die bestaat.
Wanneer je primitieve datatypes zoals int, long, boolean, ... doorgeeft aan een methode gebeurt dat byValue: enkel de waarde van de variabele wordt meegegven, de variabele zelf wordt binnen de scope van de methode niet aangepast.
Geef je objecten (dus ook arrays) door aan een methode, dan worden die gegevens byReference meegegeven, de methode werkt met het object in kwestie, het object komt er dus gemanipuleerd uit.
Bestudeer aandachtig volgend voorbeeld, voer het zeker uit en bekijk het resultaat, probeer de werking te begrijpen.
public class Doorgeef {
public int getalwaarde;
public static int verdubbel(int waarde){
return waarde *= 2;
}
public void verdubbelgetalwaarde(Doorgeef B){
B.getalwaarde *= 2;
}
public void verdubbelaar(int a[]){
for(int teller=0;teller<a.length;teller++){
a[teller] *= 2;
}
}
public static void main(String[] args) {
int getal = 50;
System.out.println(getal);
System.out.println(Doorgeef.verdubbel(getal));
System.out.println(getal);
System.out.println("\n");
Doorgeef test = new Doorgeef();
test.getalwaarde = 60;
System.out.println(test.getalwaarde);
test.verdubbelgetalwaarde(test);
System.out.println(test.getalwaarde);
System.out.println("");
int mijnarray[] = {1,2,3,4,5,6};
Doorgeef test2 = new Doorgeef();
//arrayinhoud voor verdubbelaar
for(int teller=0;teller<mijnarray.length;teller++){
System.out.println("mijnarray[" +teller +"] = " +mijnarray[teller]);
}
//verdubbelaar uitvoeren
test2.verdubbelaar(mijnarray);
System.out.println("");
//arrayinhoud na verdubbelaar
for(int teller=0;teller<mijnarray.length;teller++){
System.out.println("mijnarray[" +teller +"] = " +mijnarray[teller]);
}
}
}
De klasse Arrays uit het pallet java.util bevat in Java tal van bijzonder interessante methodes voor het doorzoeken en sorteren van Array-objecten.
Het is dan ook af te raden zelf sorteeralgoritmes te schrijven die deze functionaliteiten afhandelen.
import java.util.*;
public class arraysklasse {
public static void print(int[] a){
for(int teller=0;teller<a.length;teller++){
System.out.println("element " +teller +" = " +a[teller]);
}
}
public static void main(String[] args) {
int[] getallen = {8,150,23,46,5,89,75,23};
print(getallen);
Arrays.sort(getallen);
print(getallen);
}
}
Voor ons, als beginnende Java-programmeur is het gewoon interessant te weten dat deze klasse een heel krachtige aanvulling vormt op Arrays. Een ArrayList moet je niet meer voordimensioneren en je kan er gegevens aan toevoegen, verwijderen, wijzigen met behulp van voorgedefiniëerde methoden.
import java.util.*;
public class arrlist {
public static void main(String[] args) {
ArrayList alist = new ArrayList();
alist.add("Brugge");
alist.add("Gent");
alist.add("Oostkamp");
alist.add("Aartrijke");
System.out.println(alist);
System.out.println(alist.contains("Oostkamp"));
alist.remove(2);
System.out.println(alist);
System.out.println(alist.contains("Oostkamp"));
Collections.sort(alist);
System.out.println(alist);
}
}
Meer info over de klasse ArrayList bij Sun
Meer info over de klasse Collections (sorteren, zoeken, ...) bij Sun
In het pakket java.util bevinden zich nog tal van andere heel interessant klassen (hashtable, Linkedlist, Calendar,...) zeker eens bekijken !
| Meer tutorials: |
| leer ook: | html | | xhtml | | css | | asp | | asp.net | | c# | | ado.net | | linq | | ajax | | java | | javascript |