[Java] Polymorphism och inheritance

Permalänk
Medlem

[Java] Polymorphism och inheritance

Frågan gäller då det som står i titeln.

Jag är väldigt ny på det här och försöker förstå hur det hela går ihop.

Så här långt har jag kommit:
main-klassen:

public class Hero { public static void main(String[] arg){ Animal[] AL = new Animal[2]; Gopher gopher = new Gopher(); Unicorn unicorn = new Unicorn(); AL[0]=gopher; AL[1]=unicorn; for(Animal x : AL){ System.out.println(x.getName()); x.property(); System.out.println(); } } }

superklassen:

public class Animal{ String name; public void property(){ System.out.println("All animals have got different properties."); } public String getName(){ return this.name; } }

de sista två:

public class Unicorn extends Animal{ String name = "Unicorn"; public void property(){ System.out.println("*Twinkles beautifully in the morning sun*"); } }

public class Gopher extends Animal{ String name = "Gopher"; public void property(){ System.out.println("*Turns around dramatically*"); } }

Det jag vill göra är att ha en lokal variabel i subklasserna (om det heter så på svenska) där metoden för att få fram den finns i superklassen. I det här fallet är det ett namn, men annars skulle det kunna vara en konstant för formler ex. Jag hoppas ni förstår vad jag menar

Skriv gärna om jag gör något annat fel utöver det jag frågar om; jag vill ju inte lära mig att göra fel, så att säga.

Permalänk
Hedersmedlem

Nej det går, så vitt jag vet inte att göra (undantaget "fusk" som reflection).
Men du kanske ska börja med att använda abstract

public abstract class Animal{ String name; public abstract void property(); public String getName() { return name; } } public class Unicorn extends Animal { public Unicorn () { name = "Unicorn"; } public void property(){ System.out.println("*Twinkles beautifully in the morning sun*"); } } public class Gopher extends Animal { public Gopher () { name = "Unicorn"; } @Override public void property() { System.out.println("*Turns around dramatically*"); } }

Abstrakt gör att klassen inte kan instansieras, man måste göra en subklass för att använda den. Alla metoder som deklarerar som abstract behöver inte ha något innehåll, det är också något som en subklass måste implementera.

Som du hade så fanns det två name-variabler. Man skulle kunna nått den övre med koden super.name. Nu finns det bara en och subklasserna ställer in det i sin konstruktor.

Edit:
Ett annat sätt att ha det kan vara detta:

abstract class Animal{ final String name, property; public Animal (String name, String property) { this.name = name; this.property = property; } public String getName() { return name; } public void property() { System.out.println(property); } } class Unicorn extends Animal { public Unicorn () { super ("Unicorn", "*Twinkles beautifully in the morning sun*"); } } class Gopher extends Animal { public Gopher () { super("Unicorn", "*Turns around dramatically*"); } }

Man låter alltså inte underklasserna bestämma vad som ska hända när man anropar property utan istället så ser man till att det sker i Animal. Men property () är inte deklarerad som final så en subklass kan ersätta den med något annat om man skulle vilja.
Observera att name och property är final så de går inte att ändra på efter konstruktorn har satt dem. En annan variant är att behålla i subklasserna men att också deklarera dem som static. Då är de inte längre instansvariabler utan klassvariabler. Så i minnet finns det bara ett en enda Sträng med innehållet, för alla instansierade objekt.

Visa signatur

Forumregler | Feedbackforumet | Något som behöver modereras? Tryck på Anmäl inlägget och ge en anledning, någon moderator kommer granska inlägget och göra (egen) bedömning
"Fate. Protects fools, little children and ships named Enterprise." - Riker - ST:TNG

Permalänk
Medlem
Skrivet av Aqualize:

Nej det går, så vitt jag vet inte att göra (undantaget "fusk" som reflection).
Men du kanske ska börja med att använda abstract

[...]

Abstrakt gör att klassen inte kan instansieras, man måste göra en subklass för att använda den. Alla metoder som deklarerar som abstract behöver inte ha något innehåll, det är också något som en subklass måste implementera.

Som du hade så fanns det två name-variabler. Man skulle kunna nått den övre med koden super.name. Nu finns det bara en och subklasserna ställer in det i sin konstruktor.

Tack, jag funderade just på om det skulle användas en abstract där (just eftersom att Animal inte returnerar något värde).

Nu fick jag det att fungera genom att göra så här:

public class Hero { public static void main(String[] arg){ Animal[] AL = new Animal[2]; Gopher gopher = new Gopher(); Unicorn unicorn = new Unicorn(); AL[0]=gopher; AL[1]=unicorn; for(Animal x : AL){ System.out.println(x.getName()); x.property(); System.out.println(); } } } public abstract class Animal{ String name; public abstract void property(); public String getName(){ return this.name; } } public class Gopher extends Animal{ public Gopher(){ super.name = "Gopher"; } public void property(){ System.out.println("*Turns around dramatically"); } } public class Unicorn extends Animal{ public Unicorn(){ super.name = "Unicorn"; } public void property(){ System.out.println("*Twinkles beautifully in the morning sun*"); } }

Permalänk
Hedersmedlem
Skrivet av DaiNeaA:

[...]
Det jag vill göra är att ha en lokal variabel i subklasserna (om det heter så på svenska) där metoden för att få fram den finns i superklassen. I det här fallet är det ett namn, men annars skulle det kunna vara en konstant för formler ex. Jag hoppas ni förstår vad jag menar
[...]

Kanske glömde att svara på det. Du skulle kunna använda abstrakta metoder i superklassen för det. Så t.ex. metod 1 är vanlig och beräknar någonting, men anropar metod 2 som är abstrakt deklarerad. I en underklass så är den implementerad och vars enda uppgift är att returnera ett värde.
Eller så används som jag gjort medlemsvariabler i superklassen men de sätts i konstruktorn i subklasserna.

Visa signatur

Forumregler | Feedbackforumet | Något som behöver modereras? Tryck på Anmäl inlägget och ge en anledning, någon moderator kommer granska inlägget och göra (egen) bedömning
"Fate. Protects fools, little children and ships named Enterprise." - Riker - ST:TNG

Permalänk
Medlem
Skrivet av Aqualize:

Kanske glömde att svara på det. Du skulle kunna använda abstrakta metoder i superklassen för det. Så t.ex. metod 1 är vanlig och beräknar någonting, men anropar metod 2 som är abstrakt deklarerad. I en underklass så är den implementerad och vars enda uppgift är att returnera ett värde.
Eller så används som jag gjort medlemsvariabler i superklassen men de sätts i konstruktorn i subklasserna.

Så man kan alltså använda icke-abstrakta metoder i en abstrakt klass?

Hur menar du i exemplet? Hänger inte riktigt med på att metod 2 ska returnera att värde.

Permalänk
Hedersmedlem
Skrivet av DaiNeaA:

Så man kan alltså använda icke-abstrakta metoder i en abstrakt klass?

Hur menar du i exemplet? Hänger inte riktigt med på att metod 2 ska returnera att värde.

Ja man kan göra icke-abstrakta. Man får alltså implementera dem så de är färdiga att använda i subklasser (eller om de är statiska metoder så man inte behöver instansiera något).

På det senare tänkte jag sådant här:

abstract class MySuperClass { double doCalculations (int y, int x) { return y * x * getConstant(); } abstract double getConstant(); } class MySubClass extends MySuperClass { @Override double getConstant() { return 3.14159; } }

Men det är ju inte speciellt fin lösning, du måste ju ha en funktion för varje konstant.

Visa signatur

Forumregler | Feedbackforumet | Något som behöver modereras? Tryck på Anmäl inlägget och ge en anledning, någon moderator kommer granska inlägget och göra (egen) bedömning
"Fate. Protects fools, little children and ships named Enterprise." - Riker - ST:TNG

Permalänk
Medlem
Skrivet av Aqualize:

Ja man kan göra icke-abstrakta. Man får alltså implementera dem så de är färdiga att använda i subklasser (eller om de är statiska metoder så man inte behöver instansiera något).

På det senare tänkte jag sådant här:

abstract class MySuperClass { double doCalculations (int y, int x) { return y * x * getConstant(); } abstract double getConstant(); } class MySubClass extends MySuperClass { @Override double getConstant() { return 3.14159; } }

Men det är ju inte speciellt fin lösning, du måste ju ha en funktion för varje konstant.

Tack, då förstår jag
En till fråga bara, måste man använda @Override innan "double getConstant()"?

Permalänk
Hedersmedlem
Skrivet av DaiNeaA:

Tack, då förstår jag
En till fråga bara, måste man använda @Override innan "double getConstant()"?

Nej. Det är en annotation (anteckning), en sak som kom med i Java 1.5
Java annotation - Wikipedia, the free encyclopedia

Har man @Override på en metod så kommer kompilatorn ge felmeddelande om den inte ersätter någon metod i en superklass eller implementerar en metod från ett interface. Detta gör att man enklare upptäcker om man t.ex. stavar fel på metodnamnet när man ska ersätta en metod i en superklass.

Visa signatur

Forumregler | Feedbackforumet | Något som behöver modereras? Tryck på Anmäl inlägget och ge en anledning, någon moderator kommer granska inlägget och göra (egen) bedömning
"Fate. Protects fools, little children and ships named Enterprise." - Riker - ST:TNG