1. Studiebesök på ICA

  1. abstract class Frukt { abstract int pris(); } class Äpple extends Frukt { int pris() { return styckePris; } static int styckePris = 5; } class Apelsin extends Frukt { int pris() { return styckePris; } static int styckePris = 10; }
  2. class Påse { ArrayList frukter = new ArrayList(); void addera( Frukt f ) { frukter.add(f); } int summera() { int sum = 0; for (Iterator i = frukter.iterator(); i.hasNext(); ) { sum += ((Frukt) i.next()).pris(); } return sum; } } OBS! Klassen Påse kan lika gärna implementeras med hjälp av en vanlig array (20 lång enligt uppgiftstexten).

2. Undantag

  1. Man deklerarar subklasser till Exception. Exempel: public class MyException extends Exception { public MyException() { super(); } public MyException(String s) { super(s); } }
  2. Nyckelorden throw, try och catch används. Man använder try-block runt den kod som kan kasta undantag (med throw) och sedan catch-satser (undantagshanterare) för att ta hand om felen som eventuellt inträffat. try { ... kod som kan generera undantag } catch (undantag1 u1) { ... kod som tar hand om undantag 1 } catch (undantag2 u2) { ... kod som tar hand om undantag 2 } finally { ... kod som alltid anropas vare sig fel inträffat eller ej } Att kasta undantag: if (fel inträffat) throw new undantag1(ev. parametrar)
  3. Nyckelordet throws används i metoddeklarationer för att signalera att metoden kan kasta undantag. Man kan kasta fel vidare i.st.f. att ta hand om dem med try och catch. void metoden(parametrar) throws undantag1, undantag2 { } betyder att metoden metoden kan kasta undantag av de två specificerade typerna.

3. Cyklar och bilar

abstract class Fordon { public Fordon( int passagerarplatser) { this.passagerarplatser = passagerarplatser; } private int passagerarplatser; public int hämtaPassagerarplatser() { return passagerarplatser; } } abstract class Motorfordon extends Fordon { public Motorfordon( int motorstyrka, int passagerarplatser ) { super( passagerarplatser); this.motorstyrka = motorstyrka; } public int hämtaMotorstyrka() { return motorstyrka; } private int motorstyrka; } class Bil extends Motorfordon { public Bil( int motorstyrka, int passagerarplatser ) { super( motorstyrka, passagerarplatser ); } } class Buss extends Motorfordon { public Buss( int motorstyrka, int passagerarplatser ) { super( motorstyrka, passagerarplatser ); } } class Cykel extends Fordon { public Cykel( int passagerarplatser ) { super( passagerarplatser); } } public class Fordonstest { public static void main( String[] args ) { Fordon[] f = new Fordon[3]; f[0] = new Bil(100, 6); f[1] = new Bil(200, 100); f[2] = new Cykel(0); System.out.println( styrka(f)); System.out.println( platser(f)); } static int styrka( Fordon[] f) { int sum = 0; for (int i=0;i<f.length;i++) { if ((f[i] instanceof Motorfordon)) sum += ((Motorfordon) f[i]).hämtaMotorstyrka(); } return sum; } static int platser( Fordon[] f ) { int sum = 0; for (int i=0;i<f.length;i++) { sum += f[i].hämtaPassagerarplatser(); } return sum; } } Som alternativ till instanceof-testen kan man tänka sig att skriva hämtaMotorstyrka() i basklassen Fordon.

Vid en noggrannare läsning av uppgiftstexten framgår att metoden styrka() ska ta ett antal Motorfordon som argument. Koden förenklas då:

static int styrka( Motorordon[] f) { int sum = 0; for (int i=0;i<f.length;i++) { sum += f[i].hämtaMotorstyrka(); } return sum; }

4. Udda tester

  1. interface Heltalstest { public boolean testa( int x); } class Udda implements Heltalstest { public boolean testa( int x) { return x%2 == 1; } } class Mindre implements Heltalstest { Mindre( int x0 ) { x = x0; } public boolean testa( int y) { return y<x; } private int x; }
  2. class TestHeltalstest { public static void main(String[] args ) { Collection c = new ArrayList(); c.add( new Integer(1) ); c.add( new Integer(2) ); c.add( new Integer(3) ); c.add( new Integer(25) ); c.add( new Integer(26) ); System.out.println( c ); System.out.println( filter(c, new Udda())); } public static Collection filter( Collection c, Heltalstest test ) { Collection n = new ArrayList(); for (Iterator i = c.iterator(); i.hasNext();) { Integer v = (Integer) i.next(); if (test.testa( v.intValue())) n.add(v); } return n; } }
  3. class Och implements Heltalstest { Och( Heltalstest t1, Heltalstest t2 ) { this.t1 = t1; this.t2 = t2; } public boolean testa( int x) { return t1.testa(x) && t2.testa(x); } private Heltalstest t1; private Heltalstest t2; } Exempel på hur ett heltalstest som testar om talet är udda och mindre än 24 kan se ut: Heltalstest t = new Och( new Udda(), new Mindre(24) );

5. Arv, interface, polymorfi

  1. Arv används för att bygga klasser som återanvänder superklassens metoder och attribut och dessutom kan lägga till egna eller ändra superklassens beteende (polymorfi)
  2. Vid anrop av superklassens konstruktor samt för att komma åt metoder och variabler med samma namn i superklassen.
  3. Vid arv ska subklassen vara en sorts superklass (is-a) metod; vid sammansättning (komposition) skall en av klasserna (aggregatet) innehålla (has-a) en annan klass.
  4. Att programmet är modulärt betyder bl.a. att det är uppdelat på ett sådant sätt att ändringar i en del (t.ex. i specifikation eller i användargränssnittet) inte påverkar andra delar. Det skall också vara möjligt att återanvända klasser (endera som de är eller genom arv) i andra liknande problem. Det skall gå att förstå en del av programmet genom att studera endast någon eller några moduler. För att uppnå modularitet kombinerar man i möjligaste mån redan existerande moduler.

6. I skogen

  1. Skogen Är Full Av Lingonben! Är Skogen Full Av Lingonben? Av Lingonben Är Skogen Full.
  2. Ja, B är en subtyp till A och C är en subtyp till B. Vad betyder subtyp? Jag tolkar det som samma som subklass.

7. Baklängesord

import java.util.*; import java.io.*; public class Baklanges { public static void main(String[] args) { Set ordlistan = new TreeSet(); try { BufferedReader in = new BufferedReader(new FileReader(args[0])); String word; while((word = in.readLine()) != null) { ordlistan.add( word ); } } catch(IOException e) { System.err.println(e); System.exit(1); } Set funna = leta( ordlistan ); for (Iterator i = funna.iterator(); i.hasNext(); ) { String s = (String) i.next(); System.out.println(s + " " + baklänges(s) ); } } private static String baklänges( String s ) { String bak = ""; for (int i = s.length()-1; i >=0; i--) bak = bak + s.charAt(i); return bak; } private static Set leta( Set ordlistan ) { Set funna = new TreeSet(); for (Iterator i = ordlistan.iterator(); i.hasNext(); ) { String s = (String) i.next(); String bak = baklänges( s ); if (!funna.contains(bak)) if (ordlistan.contains(bak)) { funna.add(s); } } return funna; } }

8. GUI

Mycket schematisk kod: class XX extends Frame { main() { skapa fönster med textfält och knappar i; addera dem till XX med metoden add koppla lyssnarna till komponentnerna } class MyActions extends ActionListener { public void actionPerformer() { kolla i vilken komponent något skedde och gör vad som skulle göras } } } Klassen Graphics behöver vi inte bry oss om eftersom alla våra komponenter ritar om sig själva vid behov.

När användaren klickar på en knapp utförs något i MyActions och när fönster blir synligt anropas paint() (men eftersom Frame då anropar paint() för alla komponenterna automatiskt behöver vi inte göra något). Om vi hade t.ex en Canvas med något grafik vi själva producerat skulle vi också behöva skriva en egen paint().