Föreläsning 8 - del 2: Objektorienterad programmering - avancerat Johan Falkenjack johan.falkenjack@liu.se Linköpings universitet Sweden December 4, 2013 1
Innehåll Arv och andra viktiga begrepp Abstrakta klasser och interface Repetition av modifierare December 4, 2013 2
Begrepp - Arv Generalisering/specialisering Transitiv relation En relation mellan klasser För att kunna deklarera en klass som en "utökning" (extension) av en redan existerande klass från vilken den kan ärva egenskaper Exempel: klassen Flygplan och klassen Passagerarflygplan Ett flygplan har attribut (egenskaper) såsom position, mängden bränsle och nuvarande höjd och metoder för att ändra dess höjd, starta, landa osv. Ett passagerarflygplan ärver alla attribut och metoder som ett flygplan har (det är ju också ett flygplan!) men har dessutom ett antal säten för passagerare och metoder för att ändra aktuellt antal passagerarer - ett passagerarflygplan är en utökning/ specialisering När vi skapar en instans (objekt) av typen (klassen) Passagerarflygplan får det alla attribut och metoder, både från Passagerarflygplan och de som ärvs från klassen Flygplan December 4, 2013 3
Begrepp - Arv (forts) Superklass (generell klass) = klassen som vi ärver från Subklass (mer specifik klass, utvidgning) = den mer specifika klassen som ärver från superklassen Varför behöver vi arv? Ett bra sätt att beskriva verkligheten Hantera komplexitet - vi behöver inte beskriva alla attribut och metoder i en och samma klass och vi kan ha grupper av klasser som ärver från en och samma superklass Förbereda förändingar - vi kan lägga till nya specifika klasser som ärver från existerande Ärvs alltid alla attribut och metoder som de är? Default: ja! Inte om de är deklarerade som private använd protected istället om de även direkt ska kommas åt av subklasser Överskuggning av publika metoder Vi kan i subklassen deklarera en ny metod med samma namn som den i superklassen, men med en ny kropp December 4, 2013 4
Arv i Java Kom ihåg: arv - relationen "är en/ett": Passagerarflygplan är ett Flygplan, dvs ärver alla egenskaper från klassen Flygplan men kan utöka dessa med egna egenskaper Passagerarflygplan är subklass, Flygplan superklass Relationen är transitiv - vi skapar en hierarki Vi har redan sett detta... klasshierarkin i Javas standardbibliotek: December 4, 2013 5
Arv i Java (forts.) Alla klasser i Java ärver från java.lang.object - alla klasser är direkta eller indirekta subklasser av Object (kallas även "roten" i klasshierarkin) java.lang.object har ett antal metoder som därigenom kan användas för alla objekt (instanser) av alla klasser equals(object o) för att kontrollera om ett annat objekt är detsamma som ("lika med") detta getclass() som returnerar den klass som ett objekt tillhör (vid aktuell programkörning) - dvs "av vilken typ är detta objekt?" tostring() som returnerar en textsträng som representerar det här objektet Vi kan överskugga dessa metoder (inte getclass() som är final) i en subklass, dvs göra en egen variant som passar just vår typ av objekt December 4, 2013 6
Arv i Java (forts.) När vi vill ange att en klass är en subklass av en viss klass använder vi nyckelordet extends ("utvidgar") public class Passagerarplan extends Flygplan {! }!!//klassens kropp! Skriver vi ingenting antas att klassen bara utvidgar (dvs är en direkt subklass av) java.lang.object! December 4, 2013 7
Begreppet "överskugga" Normalt ärvs en metod som den är, dvs koden körs såsom den står i superklassen......men ibland vill man göra en ny variant av metoden som passar bättre för just den här (sub-)klassen Vanligt vid arv från väldigt generella klasser, som inte kan "veta om" behoven hos subklasserna Exempel: metoder som ärvs från java.lang.object December 4, 2013 8
Överskugga metoder - exempel tostring() (från java.lang.object) är en vanlig metod att överskugga Metoden ska skapa en lämplig textrepresentation av den aktuella klassen (t ex för utskrift på skärmen) Från dokumentationen av klassen java.lang.object i standardbiblioteket vet vi hur hur dess signatur ser ut: public String tostring()...och vad den ska göra: "Returns a string representation of the object. In general, the tostring method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read." Exempel: public class BankKonto { private int kontonr; private String kontohavare; private double saldo; } public String tostring() { return "Konto " + kontonr + " har kontohavare " + kontohavare + " och saldo " + saldo; } December 4, 2013 9
Överskugga en metod - hur gör man? Läs på om metoden som du ska överskugga din variant av metoden ska ha samma signatur (namn och parameterlista) och returtyp din variant av metoden bör göra i princip samma sak som den överskuggade metoden, men anpassat för din klass Skapa en metod i din klass med samma signatur och returtyp som den du vill överskugga Skriv koden för din metod som vanligt December 4, 2013 10
Polymorfism Vi kan avgöra ett objekts typ när programmet körs! I Java kan man definiera metoder som accepterar argument av en generell typ (superklass) och sedan behandlar dem på lämpligt sätt utan att man behöver testa vad det faktiskt är för typ (subklass) "Rätt" metod anropas automatiskt om subklassen överskuggar en mer generell metod Exempel: det kan finnas flera varianter av metoden tostring() - generella varianter och mer specifika varianter i subklasser som existerar samtidigt Även om vi bara vet att en viss variabel lagrar objekt av typen java.lang.object kommer rätt tostring()-metod (den mest specifika metoden som gäller för objektets typ) väljas automatiskt när vi anropar tostring() på objektet December 4, 2013 11
Abstrakta klasser (överkurs - men ni ska känna till begreppet) En abstrakt klass är en "ofullständig klass" Det går inte att skapa instanser av en abstrakt klass Istället används en abstrakt klass bara för att skapa mer specialiserade klasser (subklasser) som utvidgar den Den innehåller ofullständiga metoder, utan metodkropp, men den kan även innehålla konkreta metoder och variabler Varför? I vissa lägen vill vi bryta ut generella egenskaper och metoder och lägga dem i en superklass, men utan att vi kan specificera dem fullständigt Exempel InputStream - en abstrakt klass som representerar alla typer av strömmar som kan ge indata till ett program Talar om att alla mer specifika strömmar som utvidgar den här klassen måste ha metoden read() och close() t ex public abstract int read() throws IOException; Gör att vi har en möjlighet att i våra program deklarera variabler av typen InputStream och hantera dem utan att vi behöver veta exakt vilken typ av ström (subklass) instansen egentligen tillhör December 4, 2013 12
Interface Ett interface (sv. gränssnitt - förväxla inte med grafiska gränssnitt) är en klass som inte innehåller någon kod alls Vi kan inte skapa en instans av ett gränssnitt, bara av klasserna som implementerar gränssnittet Används för att beskriva ett "mönster" som andra klasser kan använda/implementera Att en klass implementerar ett visst gränssnitt gör att vi vet vad vi kan göra med den klassen - vi vet att den följer mönstret! Ungefär som ett "kontrakt" som klassen ska uppfylla Kan beskriva variabler och metoder som måste finnas och deras egenskaper implements istället för extends December 4, 2013 13
Exempel: Comparable Ett vanligt gränssnitt att implementera är Comparable man kan se det som att man ger sin klass en speciell egenskap genom att göra den "jämförbar" - vi låter den följa mönstret för en "jämförbar klass" (= gränssnittet Comparable) implements Comparable<T> - i klassdeklarationen Comparable<T> - metoden compareto(t o) vi måste ha en metod compareto(t o) som kan jämföra en given instans av klassen med ett objekt av typen T (T ersätts med en typ, dvs klass - kanske klassen självt) returnerar -1 om aktuellt objekt är "mindre än" parametervärdet, 0 om de är lika och 1 om aktullet objekt är större än parametervärdet compareto(bankkonto konto) Vill vi sortera på kontonummer eller namn? Jämföra saldo? Beror på vad vårt program ska göra! Exempel: sortera konton i kontonummerordning December 4, 2013 14
Exempel: Comparable för bankkonton - sortera i nummerordning public class BankKonto implements Comparable<BankKonto> { private int kontonr; private String kontohavare; private double saldo; // här finns alla "getters & setters" inkl. getnr() // som returnerar värdet på kontonr-variabeln } public int compareto(bankkonto konto2) { if(kontonr < konto2.getnr()) return -1; else if(kontonr == konto2.getnr()) return 0; else return 1; } December 4, 2013 15
Exempel: Comparable för bankkonton - sortera i nummerordning (annan variant) public class BankKonto implements Comparable { private int kontonr; private String kontohavare; private double saldo; // här finns alla "getters & setters" inkl. getnr() // som returnerar värdet på kontonr-variabeln public int compareto(object o) { if (o instanceof BankKonto){ //Notera typkonverteringen nedan BankKonto konto2 = (BankKonto) o; if(kontonr < konto2.getnr()) return -1; else if(kontonr == konto2.getnr()) return 0; else return 1; } else throw new IllegalArgumentException(); } } December 4, 2013 16
Exempel: Använda compareto() för bankkonton public static void main (String[] args){ BankKonto konto1 = new BankKonto(1234, "Eva", 129.50); BankKonto konto2 = new BankKonto(2345, "Anna", 12.50); int jamforelse = konto1.compareto(konto2); if (jamforelse == -1) System.out.println("Konto 1 kommer före " + "konto 2 om vi sorterar på " + "kontonr"); else if (jamforelse == 0) System.out.println("Konto 1 och konto 2 " + "har samma kontonummer - det är" + " samma konto"); else System.out.println("Konto 2 kommer före konto" + " 1 om vi sorterar på kontonr"); } December 4, 2013 17
Sammanfattning av modifierare (utökad) Klasser Offentlig - public Pakettillgänglig - (om inget sägs) Nästlade klasser (klass i klass) - private Abstrakt - abstract Omöjlig att utvidga (inga subklasser) - final Interface Offentligt - public Pakettillgängligt - (om inget sägs) Metod i en klass Offentlig - public Pakettillgänglig - (om inget sägs) Skyddad (åtkomst från subklasser + paketet) - protected Privat för den klassen - private Klassmetod (statisk metod) - static Instansmetod - (om inte static) Abstrakt - abstract Omöjlig att överskugga - final December 4, 2013 18
Sammanfattning av modifierare (utökad) Variabel Offentlig - public Pakettillgänglig - (om inget sägs) Skyddad (åtkomst från subklasser + paketet) - protected Privat för den klassen - private Klassvariabel (statisk variabel) - static Instansvariabel - (om inte static) Konstant - final Fyra kategorier = fyra beslut Åtkomst (offentlig, paket, skyddad, eller privat)? Klass- eller instans (-variabel/-metod)? Möjlig att ändra (överskugga, utvidga)? Abstrakt eller konkret? December 4, 2013 19
Sammanfattning Arv Superklass - subklass Subklass ärver variabler och metoder från superklass men kan utöka dessa med mer specifika variabler/metoder extends! Överskugga Skapa en egen variant av en metod i en subklass Abstrakta klasser "Halvfärdiga" klasser som bara är tänkta att användas för att skapa subklasser av abstract! Interface "Tomma klasser", kan inte instansieras "mönster"/"kontrakt" som en klass kan följa implements! December 4, 2013 20
December 4, 2013 21