Lektion 9
Delklasser & Arv Arv & Skuggning
Arv
En människa har en far och en mor
Egenskaper från föräldrar ärvs till barnen
“Är-en”-relationen
En rektangel är en figur
En kvadrat är en rektangel som är en figur
I Java kan klasser ärva varandra
Delklasser
“Är-en” motsvarar en delklass
En delklass/subklass utvidgar en superklass
D är en delklass av S, S är en superklass till D
D ärver egenskaperna från sin superklass S
Klassen S
Klassen D
Mer arv
En klass K1som utvidgar en klass K2ärver metoder och variabler från klassen K2.
Metoder och variabler i K2blir alltså även metoder och variabler i K1även om de ej är deklarerade där
Konstruktorer och privata variabler ärvs ej
Det finns alltid bara ett exemplar av statiska variabler oavsett hur många utvidgningar som gjorts.
Med final kan man förhindra att en klass utvidgas
Javadokumentation
I javadokumentationen (API) ser man
klasshierarkierna för varje klass. Klassen Integer till exempel:
Object är alla klassers superklass. Object har java.lang.Object
|
+--java.lang.Number
|
+--java.lang.Integer
Initialisering och delklasser
Eftersom konstruktorer inte ärvs får man skriva nya.
Den parameterlösa konstruktorn i superklassen anropas alltid först, därför måste den finnas med i ursprungsklassen.
Man kan använda anropet super för att komma åt superklassens konstruktorer om de skall fungera på samma sätt.
En grundklass
class Fordon{
private String färg; private int hastighet;
public Fordon(String färg){
this.färg = färg;
}
public int regleraFart(int v){
hastighet = hastighet + v;
return hastighet;
}
public void stanna(){
hastighet = 0;
} }
Utvidgning
Publika
class Bil extends Fordon{
public Bil(String färg){
super(färg);
} }
Bil är en omedelbar delklass till Fordon.
class Audi extends Bil{
public Audi(String färg){
super(färg);
} }
Audi är en omedelbar delklass till bil, men även en delklass till Fordon En Audi är en Bil som är ett Fordon
Testprogram
En klass ärver metoder från de klasser den utvidgar. Alltså kan vi nu skriva följande...
public class Test{
public static void main(String argv[]){
Audi minBil = new Audi("Grön");
minBil.regleraFart(50);
minBil.stanna();
} }
Enkelt arv & Runtime-klass
I java finns bara enkelt arv, dvs en klass kan bara ärva en omedelbar superklass.
Varje klass har en egen runtime-klass vilket gör att klasserna kan särskiljas.
En Audi kan klasskonverteras till ett Fordon och sedan tillbaks eftersom den varit en Audi
Ett Fordon som aldrig varit en Audi kan inte klasskonverteras till en Audi
Arv & Skuggning
En instansmetod i en delklass, med samma metodhuvud som i en överklass,
överskuggar överklassens deklaration.Tillåter oss att ändra beteende
Överskuggning
Vi utökar klassen Fordon med två metoder
public void svängVänster(){System.out.println("Vänster!!");
}
public void svängHöger(){
System.out.println("Höger!!");
}
Överskuggning forts...
class Boat extends Fordon{
public Boat(String serNr){
super(serNr);
}
public void svängVänster(){
System.out.println("Babord!!");
}
public void svängHöger(){
System.out.println("Styrbord");
} }
Provkör igen...
public class Test{
public static void main(String argv[]){
Audi minBil = new Audi("Grön");
minBil.regleraFart(50);
minBil.stanna();
minBil.svängVänster();
Boat minBåt = new Boat("Vit");
minBåt.svängVänster();
minBåt.svängHöger();
} }
Exempel om runtimeklassen
Boat minBåt = new Boat(“Sankta Maria2”);
Fordon mittFordon = minBåt;
/* mittFordon går att göra om till en Boat därför att mittFordon tilldelats ett objekt som är av runtimeklassen Boat.
Exempel: Fordon båt = new Boat(“Frida”);
*/
mittFordon.svängVänster();
// Skriver alltså ut Babord!!
Syftning & Överskuggade metoder
Arv kan tillhandhålla en mängd metoder
Vid ett anrop bestämmer runtimetypen var sökningen efter metoden börjar
Sedan stegar man sig upp genom klasshierarkin
Överskuggade metoder kommer man åt med super.metodnamn();
En final metod kan inte överskuggas
Polymorfa metoder
public class Fig{
public static void main(String argv[]){
Cirkel c = new Cirkel(10);
Kvadrat k = new Kvadrat(10);
c.skrivArea();
k.skrivArea();
} }
class Figur{
public double area(){
return 0.0;
}
public void skrivArea(){
System.out.println(area());
Polymorfa metoder forts... Cirkel
class Cirkel extends Figur{
private double radie;
public Cirkel(double radie) { this.radie = radie;
}
public double area(){
return Math.PI*radie*radie;
}
Polymorfa metoder forts... Kvadrat
class Kvadrat extends Figur{
private double kant;
public Kvadrat(double kant){
this.kant = kant;
}
public double area(){
return kant*kant;
} }
Arv - Exempel
Studera klassen Fruktskål nedan. Implementera klasserna Frukt, Äpple och Banan så att programmet Fruktskål fungerar.
public class Fruktskål {
public static void main(String argv[]) { Frukt skål[] = new Frukt[2];
skål[0] = new Äpple(“21 Juni”);
skål[1] = new Banan(“15 Juni”);
for(int i=0; i<skål.length; i++) { skål[i].ätUpp();
System.out.println();
} } }
Arv – Exempel - Fortsättning
När programmet Fruktskål körs skall följande utskrift syans på skärmen:
Bäst före: 21 Juni Äter upp frukten, Mums!
Skala banan Bäst före: 15 Juni Äter upp frukten, Mums!
Ledning:
Utskriften sker när en frukt äts upp, dvs i metodenätUpp() som anropas för den instans som “äts upp”
Lösning till Arv Exempel
public class Frukt{
String bästFöre;
Frukt(String bästFöre){
this.bästFöre=bästFöre;
}
public void ätUpp(){
System.out.println("Bäst före: "+bästFöre);
System.out.println("Äter upp frukten, Mums!");
} }
Lösning forts...
public class Banan extends Frukt{
Banan(String bästFöre){
super(bästFöre);
}
public void ätUpp(){
System.out.println("Skala banan");
super.ätUpp();
} }
public class Äpple extends Frukt{
Äpple(String bästFöre){
super(bästFöre);
}
public class Banan extends Frukt{
Banan(String bästFöre){
super(bästFöre);
}
public void ätUpp(){
System.out.println("Skala banan");
super.ätUpp();
} }
public class Äpple extends Frukt{
Äpple(String bästFöre){
super(bästFöre);
} }
Exempel: En Vector för primitiva datatypen int
import java.util.Vector;
public class IntVector extends Vector { public IntVector() {
super();
}
public void addElement(int value) { super.addElement(new Integer(value));
}
public int intAt(int index) {
Integer elem = (Integer)super.elementAt(index);
return elem.intValue();
} }