JAVA1 H 9. OBJECTGEORIENTEERD PROGRAMMEREN: OVERERVING 1. INLEIDING Wat is overerving (inheritance)? Overerving is een mechanisme waarbij software opnieuw wordt gebruikt: nieuwe klassen worden gecreëerd vertrekkende van bestaande klassen, waarbij de attributen en methodes worden geërfd van de basisklasse (superklasse) en uitgebreid met nieuwe mogelijkheden, noodzakelijk voor de nieuwe klasse = afgeleide klasse (subklasse). Schematisch (UML): Superklasse Subklasse erft van
JAVA2 De subklasse is normaal meer specifiek dan de superklasse en vertegenwoordigt een kleinere en meer gespecialiseerde groep van objecten. De subklasse heeft een ‘is een’ relatie met de superklasse. Het gedrag van de subklasse kan aangepast worden door methoden van de superklasse te overridden (herdefiniëren) in de subklasse. De subklasse kan zelf ook superklasse zijn voor een nieuwe subklasse. Een superklasse kan meerdere ‘directe’ subklasse hebben. Een subklasse hoort altijd maar bij één superklasse. Er ontstaat een hele hiërarchie. Protected members (data/methoden) in de superklasse zijn toegankelijk vanuit de subklasse. 1. INLEIDING
JAVA3 2. Superklasse en subklasse. De subklasse heeft een ‘is een’ relatie met de superklasse. Bij een subklasse hoort steeds één superklasse. Zo ontstaat er een strikt hiërachishe organisatie tussen de klassen. Java laat geen multiple inheritance toe. Een klasse kan wel meerdere interfaces implementeren (een beperkte vorm van multiple inheritance). De private members (attributen/methoden) van de superklasse zijn niet toegankelijk vanuit de subklasse. Wanneer de subklasse een identifier definieert die reeds in de superklasse is gedefinieerd wordt ondubbelzinnigheid vermeden door het gebruik van het Java woord super. Vb: super.paint(g);
JAVA4 3. protected members. Members in de superklasse met de toegangsclausule protected zijn toegankelijk vanuit de subklasse als eveneens vanuit iedere klasse die in hetzelfde package is gedefinieerd. protected is een afschermingsniveau tussen package en public. VB:class Superklasse { protected x; //… } class Subklasse extends Superklasse { public void doiets() { x++;//directe toegang tot protected members //…//van de Superklasse. }
JAVA5 4. Relatie tussen superklasse objecten en subklasse objecten. Voorbeeld: superklasse Point2 en subklasse Circle3. Point2 #int x #int y +Point() +Point(int, int) +setX(int):void +getX():int +setY(int):void +getY():int +toString():String Circle3 -double radius +Circle2() +Circle2(int, int, double) +setRadius(double):void +getRadius():double +getDiameter():double +getCircumference():double +getArea():double +toString():String
JAVA6 4. Relatie tussen superklasse objecten en subklasse objecten (vervolg). De superklasse Point2 (vb. pag. 414) public class Point2 { protected int x, y; public Point2() { //maakt gebruik van de constructor van Object} public Point2(int i, int j) { x=i; y=j; } public void setX(int i) {x=i;} public int getX() { return x; } public void setY(int j) {y=j;} public int getY() { return y; } public String toString() { return " [" + x + ", " + y + "] " ; } } Point erft impliciet van Object (H8). De attributen x en y zijn protected, ze zullen toegankelijk zijn in eventuele subklasse van Point (vb: Circle) In beide constructoren wordt als eerste taak impliciet de constructor van Object opgeroepen Point ‘overrides’ de methode toString van zijn ‘directe superklasse’ Object.
JAVA7 4. Relatie tussen superklasse objecten en subklasse objecten (vervolg). De subklasse Circle3. (zie pag. 415) public class Circle3 extends Point2 { private double radius; public Circle3() {// impliciete oproep van de constructor van Point2 } public Circle3(int i, int j, double straal) { x=i; y=j; setRadius(straal); } public void setRadius( double straal ) { radius = ( straal >= 0.0 ? straal : 0.0 );} public double getRadius() { return radius; } public double getDiameter() { return 2*radius; } public double getCircumference() { return Math.PI * getDiameter() } public double area() { return Math.PI * radius * radius; } public String toString() { return "Center = " + "[" + x + ", " + y + "]; Radius = " + radius; } } Circle3 erft van Point2 (Java: extends). Point2 is ‘een directe superklasse’ van Circle3. Object is ‘een indirecte superklasse’ van Circle3.
JAVA8 4. Relatie tussen superklasse objecten en subklasse objecten (vervolg). Aanpassing: attributen x en y worden PRIVATE gedeclareerd De superklasse Point3 (vb. pag. 419) public class Point3 { private int x, y; public Point3() { //maakt gebruik van de constructor van Object} public Point3(int i, int j) { x=i; y=j; } public void setX(int i) {x=i;} public int getX() { return x; } public void setY(int j) {y=j;} public int getY() { return y; } public String toString() { return " [" + getX() + ", " + getY() + "] " ; } }
JAVA9 4. Relatie tussen superklasse objecten en subklasse objecten (vervolg). De subklasse Circle4 (zie pag ) public class Circle4 extends Point3 { private double radius; public Circle4() {// impliciete oproep van de constructor van Point3 } public Circle4(int i, int j, double straal) { super(i,j); // expliciete oproep van de constructor van Point3 setRadius(straal); } public void setRadius( double straal ) { radius = ( straal >= 0.0 ? straal : 0.0 );} public double getRadius() { return radius; } public double getDiameter() { return 2*getRadius(); } public double getCircumference() { return Math.PI * getDiameter() } public double area() { return Math.PI * getRadius() * getRadius(); } public String toString() { return "Center = " + super.toString() + "; Radius = " + getRadius(); } } Voordeel: kleine veranderingen in de implementatie hoeven geen grote gevolgen meer te hebben. (vb. Naamsverandering van x en/of y in Point of van radius in Circle)
JAVA10 4. Relatie tussen superklasse objecten en subklasse objecten (vervolg). De constructor van Circle (subklasse) moet de constructor van zijn directe superklasse oproepen, impliciet of expliciet. Impliciet: de default constructor van de basisklasse wordt opgeroepen (Er moet dan wel een defaultconstructor zijn!). public Circle4() { } Expliciet: met behulp van het Java woord super public Circle4(int i, int j, double straal) { super(i,j); setRadius(straal); } Het expliciet oproepen van de superklasseconstructor moet als eerste actie in de constructor staan.
JAVA11 4. Relatie tussen superklasse objecten en subklasse objecten (vervolg). De objecten van Point3 en Circle4. Aanmaak van de objectreferenties en objecten zelf. Point3 punt1, punt2; Circle4 cirkel1, cirkel2; punt1 = new Point3(30, 50); Punt2 = new Point3(10, 40); cirkel1 = new Circle4(120, 89, 2.7); Cirkel2 = new Circle4(70, 111, 3.3); Oproep methodes: punt1.setX(35); int ycoord = punt2.getY(); cirkel1.setRadius(4.25); cirkel2.setY(20); // want cirkel2 IS EEN Point3-object! double opp = cirkel2.getArea();
JAVA12 5. Overerving op drie niveaus Voorbeeld: Punt, Cirkel, Cylinder Klasse relaties: UML diagramma. Point3 -int x -int y +Point3() +Point3(int, int) +setX(int):void +getX():int +setY(int):void +getY():int +toString():String Circle4 -double radius +Circle4() +Circle4(int, int, double) +setRadius(double):void +getRadius():double +getDiameter(): double +getCircumference(): double +getArea():double +toString():String Cylinder -double height +Cylinder() +Cylinder(int,int,double,double) +setHeight(double):void +getHeight():double +getArea():double +getVolume():double +toString():String
JAVA13 5. Overerving op drie niveaus Voorbeeld: Punt, Cirkel, Cylinder (vervolg) public class Cylinder extends Circle4 { private double height; public Cylinder() public Cylinder(int xc, int yc, double r, double h) public void setHeight(double h) public double getHeight () public double getArea() public double getVolume() public String toString() } Subklasse Cylinder: interface van Circle klasse (setX, setY, setRadius, getX, getY, getRadius, getDiameter, getCircumference + overridden getArea en toString) + extra interface van Cylinder ( setHeight, getHeight, getVolume).
JAVA14 5. Overerving op drie niveaus Voorbeeld: Punt, Cirkel, Cylinder (vervolg) De overridden methoden getArea en toString. public double getArea() { return 2 * super.getArea() + getCircumference() * getHeight(); } Voor de oppervlakteberekening van een cylinder zijn de onderkant en bovenkant cirkels: de overridden methode hergebruikt de methode van de superklasse. public String toString() { return super.toString() + " ; Height = " + getHeight; }
JAVA15 5. Overerving op drie niveaus Voorbeeld: Punt, Cirkel, Cylinder (vervolg) De objecten van Cylinder Aanmaak van de objectreferenties en objecten zelf. Cylinder cylinder; cylinder = new Cylinder(12, 23, 2.5, 5.7); Oproep methodes: double vol = cylinder.getVolume(); double diam = cylinder.getDiameter(); // geërfd van Circle4 double x = cylinder.getX(); // geërfd van Point3 double opp = cylinder.getArea(); // eigen overriden methode String s = cylinder.toString(); // eigen overriden methode
JAVA16 6. Constructors en finalizers in subklassen. Volgorde van activatie. (Vb. pag ) Bij creatie constructor methode. De constructor moet als eerste actie impliciet of expliciet de superklasse constructor activeren. De superklasse constructor wordt dus eerst afgewerkt. Bij verwijdering finalize methode. Als de finalize methoden werden gedefinieerd (moet met protected toegangclausule) dan is de laatste actie van de finalize methode het oproepen van de superklasse finalize methode. De subklasse finalize methode wordt dus eerst afgewerkt.
JAVA17 6. Constructors en finalizers in subklassen. Constructor: circle1 = new Circle(72, 29, 4.5); Point constructor construeert een punt op positie [72,29] dat het middelpunt gaat worden van de cirkel Circle constructor voegt hieraan de straal van 4.5 toe Finalizer circle1 = null; System.gc(); Eerst treedt de finalizer van Circle in werking, die de cirkel "afbreekt", zodat enkel nog een punt overblijft Dan doet de finalizer van Point zijn werk om ook nog het punt te laten verdwijnen
JAVA18 Oefening H9: Rode draad Definieer een superklasse Rekening (bestaat al): Attributen: rekeningNr (long), saldo (double) en houder (String) Methoden: constructor(met 3 arg), accessors en mutators, storten, afhalen en overschrijven. Definieer nu de subklasse ZichtRekening: Extra attributen: maxKrediet (double). Extra methoden: constructor, get en set voor maxKrediet. Override methode: setSaldo. En de subklasse SpaarRekening: Extra attributen: aangroeiIntrest (double) : voor alle spaarRekeningen dezelfde waarde!. Extra methoden: constructor, get en set AangroeiIntrest. Override methode: setSaldo.
JAVA19 class ZichtRekening extends Rekening { private double maxKrediet; public ZichtRekening(double max, long rek, double sal, String houd) { super(rek, sal, houd); setMaxKrediet(max); } public void setMaxKrediet(double max) { if (max >0.0) throw new IllegalArgumentException("MaxKrediet positief"); else maxKrediet = max; } public double getMaxKrediet() { return maxKrediet;}
JAVA20 public void setSaldo(double sal) { if (sal < maxKrediet) throw new IllegalArgumentException("Maxkrediet bereikt"); else super.setSaldo(sal); } class SpaarRekening extends Rekening { private static double aangroeiIntrest; public SpaarRekening(long rek, double sal, String houd) { super(rek, sal, houd); } public static void setAangroeiIntrest(double aangroei) { if (aangroei < 0.0) throw new IllegalArgumentException("Intrest negatief"); else aangroeiIntrest = aangroei; }
JAVA21 public static double getAangroeiIntrest() { return aangroeiIntrest; } public void setSaldo(double sal) { if (sal < 0) throw new IllegalArgumentException ("Saldo kan niet negatief worden"); else super.setSaldo(sal); }