LULEÅ TEKNISKA UNIVERSITET Tentamen i Objektorienterad programmering och design Totala antalet uppgifter: 5 Lärare: Håkan Jonsson, 491000, 073-820 1700 Resultatet offentliggörs senast: 2011-04-02. Tillåtna hjälpmedel: Inga. Kurskod D0010E Datum 2011-03-18 Skrivtid 5 tim OBS! Lösningar får inte baseras på fördefinierade klasser ur t ex Javas standardbibliotek annat än där detta uttryckligen tillåts. Sådana lösningar ger inga poäng. 1. Teori a) Ange en väsentlig skillnad mellan klass och objekt. (1p) b) Ett program består av fyra klasser A, B, C och D. Klasserna A och B ligger i paketet p medan C och D ligger i paketet q. Vidare är B och D abstrakta, och D innehåller deklarationerna: protected int i; private int j; int k; Om nu A ärver B som ärver C som ärver D, i vilka av de fyra klasserna syns då i)... i? (1p) ii)... j? (1p) iii)... k? (1p) c) På sida 3 finns en klass för FIFO-köer 1 som fungerar trots att den har vissa brister. Vilka? 2. Palindrom Svara kortfattat med radnummer och vad som är olämpligt samt hur du istället skulle ha skrivit. Lägg därefter till en lista med eventuella brister som inte har med enskilda rader att göra. (2p) Skriv en metod public static boolean ispalindrome(int[] num) som avgör om en listning av talen i en heltalsarray blir densamma oavsett från vilket håll man listar talen. Anta, om du vill, att arrayen innehåller minst ett tal (behöver inte kollas). Exempel: 1,2,3,2,1 är ett palindrom, och även 0, men inte 1,2,3,1,2,3. 3. Fotoalbum (6p) (6p) Utgå från att det redan finns en klass Photo och skriv en klass PhotoAlbum för fotoalbum med följande konstruktor och metoder: public PhotoAlbum(int maxsize) som skapar ett tomt album med plats för som mest maxsize foton. public int maxsize() som ger maximala antalet foton som ryms i albumet. public int size() som ger tillbaka aktuellt antal foton i albumet. public void append(photo p) som lägger till p sist. Fotot som läggs till ett album innehållande i foton är nr i + 1. public Photo photonum(int n) som ger tillbaka foto nr n. public void replacenum(int n, Photo p) som byter ut foto nr n mot p. 1 Ungefär som kön du implementerade i lab 3, men inte lika omfattade. 1
public void deletenum(int n) som tar bort foto nr n. Detta minskar albumets storlek med 1. Det minskar också numret på alla foton med nummer högre än n med 1. Undantag ska kastas när så är lämpligt. Tips: Representera internt fotoalbumet med en array. 4. UML (6p) RuntimeException throws KonservBurk + KonservBurk(double volym, int vikt) <<abstract>> Burk # vikt : int + Burk(double volym, int vikt) + vikt() : int throws EnLitersBurk + EnLitersBurk(int vikt) <<abstract>> Behållare # volym : double # öppen : boolean + Behållare(double volym) + volym() : double + äröppen() : boolean + öppna() : void + stäng() : void Påse + Påse(double volym) Figur 1: UML-diagram för uppgift 4. Implementera klasserna i UML-diagramet i figur 1 enligt följande: Behållare En klass representerar allmänna behållare som har viss volym (ml) och är antingen öppna eller stängda. Endast en stängd behållare kan öppnas (med öppna()), och en öppen stängas (med stäng()). Försök att öppna eller stänga i andra fall resulterar i att ett undantag kastas. Metoden äröppen() avgör om en behållare är öppen och volym() ger behållarens volym. Påse En nyskapad påse är till att börja med öppen. Burk En burk är en behållare med vikt (gram). Metoden vikt() ger vikten. Konservburk En konservburk är till att börja med stängd. Så snart den öppnats kan den inte stängas; försök att stänga den ger då ett undantag. EnLitersBurk En 1-litersburk är en burk med volymen 1000 ml. 5. Iteratorer a) Utgå från klassen på sidan 3 och inför på lämpligt sätt en möjlighet att skapa iteratorer enligt Iterator-gränssnittet bifogat sist. Metoden remove ska endast kasta undantag. Du får här, för enkelhets skull, anta att en kö inte förändras efter att en första iterator har skapats. (3p) b) När en kö förändras, genom att innehåll läggs till eller tas bort, kan man säga att det över tiden uppstår olika versioner av den. Om vi vill att iteratorer som skapats för en viss version av kön ska fungera endast så länge inga nya versioner av kön skapas, hur skulle du åstadkomma det? Ange kortfattat de förändringar och tillägg du skulle göra i klassen på sidan 3 och din iterator. (3p) 2
Bilaga: En köklass 1 public class LIFO { 2 public Item f i r s t ; 3 public Item l a s t ; 4 public int s i z e = 0 ; 5 6 public LIFO ( ) { 7 f i r s t = new Item ( ) ; // header 8 l a s t = f i r s t ; 9 } 10 11 public class Item { 12 public Item l i n k = null ; 13 public Object content ; 14 } 15 16 public int s i z e ( ) { 17 return this. s i z e ; 18 } 19 20 public void add ( Object element ) { 21 Item b2 = new Item ( ) ; 22 b2. content = element ; 23 l a s t. l i n k = b2 ; 24 l a s t = b2 ; 25 s i z e ++; 26 } 27 28 public Object f i r s t ( ) { 29 return f i r s t. l i n k ; 30 } 31 32 public void removefirst ( ) { 33 i f ( f i r s t. l i n k!= null ) { 34 Item r = f i r s t. l i n k ; 35 f i r s t = f i r s t. l i n k ; 36 s i z e ; 37 } 38 } 39 } 3
Overview Package Class Use Tree Deprecated Index Help PREV CLASS NEXT CLASS FRAMES NO FRAMES All Classes SUMMARY: NESTED FIELD CONSTR METHOD DETAIL: FIELD CONSTR METHOD Java TM 2 Platform Std. Ed. v1.4.2 java.util Interface Iterator All Known Subinterfaces: ListIterator All Known Implementing Classes: BeanContextSupport.BCSIterator public interface Iterator An iterator over a collection. Iterator takes the place of Enumeration in the Java collections framework. Iterators differ from enumerations in two ways: Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics. Method names have been improved. This interface is a member of the Java Collections Framework. Since: 1.2 See Also: Collection, ListIterator, Enumeration Method Summary boolean hasnext() Returns true if the iteration has more elements. Object next() Returns the next element in the iteration. void remove() Removes from the underlying collection the last element returned by the iterator (optional operation). Method Detail hasnext public boolean hasnext() Returns true if the iteration has more elements. (In other words, returns true if next would return an element rather than throwing an exception.)
Returns: true if the iterator has more elements. next public Object next() Returns the next element in the iteration. Returns: the next element in the iteration. Throws: NoSuchElementException - iteration has no more elements. remove public void remove() Removes from the underlying collection the last element returned by the iterator (optional operation). This method can be called only once per call to next. The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way other than by calling this method. Throws: UnsupportedOperationException - if the remove operation is not supported by this Iterator. IllegalStateException - if the next method has not yet been called, or the remove method has already been called after the last call to the next method. Overview Package Class Use Tree Deprecated Index Help PREV CLASS NEXT CLASS FRAMES NO FRAMES All Classes SUMMARY: NESTED FIELD CONSTR METHOD DETAIL: FIELD CONSTR METHOD Java TM 2 Platform Std. Ed. v1.4.2 Submit a bug or feature For further API reference and developer documentation, see Java 2 SDK SE Developer Documentation. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples. Copyright 2003, 2010 Oracle and/or its affiliates. All rights reserved. Use is subject to license terms. Also see the documentation redistribution policy.
Errata (D0010E, 2011-03-18) 1. Kommentar: I sista deluppgiften ska det verkligen stå FIFO ; implementeringen på sida 3 är en FIFO-kö trots klassens (missvisande) namn. Ett mera avvikande namn på LIFO, t ex BankKonto, hade varit tydligare. 2. 3. Förtydligande: deletenum minskar den aktuella storleken, inte den maximala. Förtydligande: replacenum ska bara byta ut foton som finns i albumet(!) Att albumet inte är fullt, och det därför finns tomma platser, ska inte blandas ihop med att varje foto har ett unikt nummer och att endast foton kan bytas ut. Numreringen följer av den ordning i vilken albumets metoder anropats. 4. 5. Kommentar: Observera att det ska kunna finnas flera iteratorer till en och samma kö. 6
Existing suggested solutions (D0010E, 2011-03-18) 1 Kommentarer på uppgift 1: a) Klasser skrivs av programmerare och ingår i programmets källkod medan objekt skapas under körning. b) i) Alla. ii) Endast D. iii) C och D. c) Följande, som inte allt är lika självklart, är brister: Klassnamnet är missvisande; borde vara FIFO. Interna tillståndet bör vara dolt, dvs private. Den interna nodklassen Item bör vara dold, dvs private. Det saknas javadoc. Det saknas interna kommentarer. T ex att first är en pre-pointer. removefirst bör reagera om man försöker ta bort ur en tom kö, t ex genom att kasta undantag (en enkel lösning är att lägga till en else-gren på ifsatsen, och i den kasta undantaget). Klassen Item skulle kunna ha metoder och konstruerare med argument (t ex innehållet). På rad 17 behövs inte this. Rad 34 behövs inte. Metoden first bör inte returnera link utan content. Att det fungerar nu beror bara på att den interna nodklassen exponeras utanför LIFO, vilket är olämpligt (se ovan). Idag skulle man med fördel kunna parametrisera LIFO med elementtypen, och därigenom komma ifrån problemet med att ett Object kan vara vad som helst. Detta skulle också omdelbart röja misstaget i first... 2 Kommentarer på uppgift 2: Metoden Math.abs bör man ha skrivit själv (beräknar absolutbeloppet) men är så enkel att den godtas i denna lösning. 1 p u b l i c s t a t i c boolean ispalindrome ( i n t [ ] num) { 2 r eturn ip (num, 0,num. length 1); 3 } 4 5 p u b l i c s t a t i c boolean ip ( i n t [ ] num, i n t i, i n t j ) { 6 i f (Math. abs ( i j )<=1) { 7 r eturn true ; 8 } e l s e { 9 r eturn num [ i ]==num[ j ] && ip (num, i +1, j 1); 10 } 11 } 3 Kommentarer på uppgift 3: 7
1 p u b l i c c l a s s PhotoAlbum { 2 3 p r i v a t e i n t maxsize ; 4 p r i v a t e i n t s i z e ; 5 p r i v a t e Photo [ ] photos ; 6 7 p u b l i c PhotoAlbum ( i n t maxsize ) { 8 t h i s. maxsize = maxsize ; 9 photos = new Photo [ t h i s. maxsize ] ; 10 s i z e = 0 ; 11 } 12 13 p u b l i c i n t maxsize ( ) { 14 return t h i s. maxsize ; 15 } 16 17 p u b l i c i n t s i z e ( ) { 18 return t h i s. s i z e ; 19 } 20 21 p u b l i c void append ( Photo p ) { 22 i f ( s i z e == maxsize ) { 23 throw new RuntimeException ( Album a lready f u l l. ) ; 24 } e l s e { 25 photos [ s i z e ++] = p ; 26 } 27 } 28 29 p r i v a t e boolean okphotonum( i n t num) { 30 return 0 <= num && num < s i z e ; 31 } 32 33 p u b l i c Photo photonum( i n t num) { 34 i f ( okphotonum (num) ) { 35 return photos [ num ] ; 36 } e l s e { 37 throw new RuntimeException ( No such photo. ) ; 38 } 39 } 40 41 p u b l i c void replacenum ( i n t num, Photo p ) { 42 i f ( okphotonum (num) ) { 43 photos [ num ] = p ; 44 } e l s e { 45 throw new RuntimeException ( No such photo. ) ; 46 } 47 } 48 49 p u b l i c void deletenum ( i n t num) { 50 i f ( okphotonum (num) ) { 51 f o r ( i n t i = num; i <= s i z e 2 ; i++) { 52 photos [ i ] = photos [ i + 1 ] ; 53 } 54 s i z e ; 55 } e l s e { 8
56 throw new RuntimeException ( No such photo to d e l e t e. ) ; 57 } 58 } 59 } 4 Kommentarer på uppgift 4: 1 a b s t r a c t c l a s s B e h å l l a r e { 2 p r o t e c t e d double volym ; 3 p r o t e c t e d boolean öppen ; 4 5 p u b l i c B e h å l l a r e ( double volym ) { 6 t h i s. volym = volym ; 7 } 8 9 p u b l i c double volym ( ) { 10 return volym ; 11 } 12 13 p u b l i c boolean äröppen ( ) { 14 return öppen ; 15 } 16 17 p u b l i c void öppna ( ) { 18 i f ( öppen ) { 19 throw new RuntimeException ( ) ; 20 } e l s e { 21 öppen = true ; 22 } 23 } 24 25 p u b l i c void stäng ( ) { 26 i f (! öppen ) { 27 throw new RuntimeException ( ) ; 28 } e l s e { 29 öppen = f a l s e ; 30 } 31 } 32 } 33 34 c l a s s Påse extends B e h å l l a r e { 35 p u b l i c Påse ( double volym ) { 36 super ( volym ) ; 37 öppen = true ; 38 } 39 } 40 41 a b s t r a c t c l a s s Burk extends B e h å l l a r e { 42 p r o t e c t e d i n t v i k t ; 43 44 p u b l i c Burk ( double volym, i n t v i k t ) { 45 super ( volym ) ; 46 t h i s. v i k t = v i k t ; 47 } 48 9
49 p u b l i c i n t v i k t ( ) { 50 return v i k t ; 51 } 52 } 53 54 c l a s s KonservBurk extends Burk { 55 p u b l i c KonservBurk ( double volym, i n t v i k t ) { 56 super ( volym, v i k t ) ; 57 öppen = f a l s e ; 58 } 59 60 p u b l i c void stäng ( ) { 61 throw new RuntimeException ( ) ; 62 } 63 } 64 65 c l a s s EnLitersBurk extends Burk { 66 p u b l i c EnLitersBurk ( i n t v i k t ) { 67 super (1000, v i k t ) ; 68 } 69 } 5 Kommentarer på uppgift 5: a) Lägg till en intern klass MyIterator som implementerar granssnittet Iterator och en metod 1 p u b l i c I t e r a t o r i t e r a t o r ( ) { 2 return new MyIterator ( ) ; 3 } Klassen berikas sen med en egen Item-referensvariabel som används för att referera in i nodlistan under iteration: 1 p r i v a t e c l a s s MyIterator implements I t e r a t o r { 2 Item ptr ; 3 4 p u b l i c MyIterator ( ) { 5 ptr = f i r s t. l i n k ; 6 } 7 8 p u b l i c boolean hasnext ( ) { 9 return ptr!= n u l l ; 10 } 11 12 p u b l i c Object next ( ) { 13 i f ( hasnext ( ) ) { 14 Object c = ptr. content ; 15 ptr = ptr. l i n k ; 16 return c ; 17 } e l s e { 18 throw new NoSuchElementException ( ) ; 19 } 20 } 21 22 p u b l i c void remove ( ) { 23 throw new UnsupportedOperationException ( ) ; 10
24 } 25 } b) I huvudklassen lägger vi till en versionsvariabel, version, ett heltal, som ökas med 1 varje gång vi förändrar kön. Vår interna klass kopierar versionsnumret till en egen variabel, myversion, och kollar sedan i samband med varje anrop till den att köns versionsnummer inte förändrats: 1 p r i v a t e c l a s s MyIterator implements I t e r a t o r { 2 Item ptr ; 3 i n t myversion ; 4 5 p u b l i c MyIterator ( ) { 6 ptr = f i r s t. l i n k ; 7 myversion = v e r s i o n ; 8 } 9 10 p u b l i c boolean hasnext ( ) { 11 i f ( myversion!= v e r s i o n ) { 12 return f a l s e ; 13 } 14 return ptr!= n u l l ; 15 } 16 17 p u b l i c Object next ( ) { 18 i f ( ( myversion == v e r s i o n ) && hasnext ( ) ) { 19 Object c = ptr. content ; 20 ptr = ptr. l i n k ; 21 return c ; 22 } e l s e { 23 throw new NoSuchElementException ( ) ; 24 } 25 } 26 27 p u b l i c void remove ( ) { 28 throw new UnsupportedOperationException ( ) ; 29 } 30 } Man kan också göra kön observerbar och låta iteratorer observera förändringar i den. Så snart en förändring sker sätts en stoppflagga i iteratorn. Denna flagga kollas i iteratorns metoder och förhindrar vidare användning av iteratorn om kön förändrats. 11