470 likes | 671 Views
Björn Eiderbäck NADA, KTH Email: bjorne@nada.kth.se Innehåll Klassdiagram i mer detalj Visibility och modifierare (vilka kommer åt attribut, metoder, osv) Abstrakta klasser och Interface Undantagshantering (Exception handling) Från UML till kod Javas API och paket.
E N D
Björn EiderbäckNADA, KTH Email: bjorne@nada.kth.se Innehåll Klassdiagram i mer detalj Visibility och modifierare (vilka kommer åt attribut, metoder, osv) Abstrakta klasser och Interface Undantagshantering (Exception handling) Från UML till kod Javas API och paket Visibility och Java API September 26, 2001
Klassdiagram (halvrepetition) • Vi kan skriva klassdiagram på en form som anger parametrar mm
Klassdiagram: notation klassbox, lång form Klass Klassnamn attribut : Typ = initialtVärde operation(argumentlista) : returTyp klassbox, kort form Klassnamn superklass (basklass) Supertyp Generalisering subklass (härledd klass) Subtyp1 Subtyp2
Strukturen av en klass representeras av attribut Attributen kan hittas genom att utforska klassdefinitioner, från kravspecifikationen och med hjälp av domänkunskap Klass: attribut Varje kurs har ett nummer, en plats där den genomförs och en tid då den går CourseOffering number location time
Person name : String age : Integer : Person name = Kalle age = 25 : Person name = Lisa age = 23 Exempel: Klassen Person med två instanser Rita en klass Person med hjälp av a) ett klassdiagram med attributen name: String och age: Integer b) två instanser av klassen Klass Instanser
FärgatObjekt color : Color = röd position : Point = (10, 10) geo1: FärgatObjekt color = röd position = (10, 10) geo2: FärgatObjekt color = röd position = (30, 50) Exempel: Färgat geometriskt objekt, med defaultvärden Rita ett klassdiagram med med ett geometriskt objekt a) där defaultvärdet för färgen är röd och för positionen är (10, 10) b) "rita" också två instanser defaultvärden eget namn (frivilligt)
Visibility • Vi kan också ange om attribut och metoder syns utanför den aktuella klassen
Modifierare visibility name : type-expression = initial-value { property-string } där visibility någon av: + public visibility (dvs alla kan använda det) # protected visibility (dvs endast synlig i klassen eller dess subklasser) - private visibility (endast synlig i klassen) understruken betyder klassmetoder och attribut Klassnamn om visibility inte sätts ut betyder det bara att den inte visas (inte att den är privat eller publik) +publikt_attribut #protected_attribut -privat_attribut klassvariabel +publik_operation() #protected_operation() -privat_operation() klassmetod()
Exempel: modifierare Person # name : String # dateOfBirth : Date - pinCode : Integer + name() : String + age() : Integer + equals(Person) : boolean # name(String) + create(name : String, dateOfBirth : Date) : Person - hashCode() : Integer
Modifierare i Java • I Java kan vi använda följande modifierare: • public • kan användas överallt • protected • kan användas i klass eller subklasser • private • kan bara användas inne i klassens beskrivning • static • klassmetod eller klassvariabel • final • kan ej ändras (variabelfallet), kan ej subklassas (klassfallet) • abstract • måste specificeras i subklasser • ingen • package visibility
Abstrakta metoder och klasser • En klass kan deklareras abstrakt • Då kan inga instanser av klassen skapas • En klass kan deklarera en eller flera av sina metoder som abstrakta • Då blir också klassen automatiskt abstrakt • Inga instanser av klassen kan därför skapas • En subklass blir också abstrakt till dess att alla abstrakta metoder fått en definition • Tex om metoderna m1() och m2() deklarerats abstrakta i klassen A men subklassen B endast implementerar m1() så är B också abstraktOm en klass C deklareras som subklass till B och implementerar m2() så blir C konkret och kan instansieras
Exempel: abstrakt klass abstract class GraphicObject{ int x, y; ... void moveTo(int newX, int newY) {...} abstract void draw(); } class Circle extends GraphicObject { void draw() {...} } class Rectangle extends GraphicObject { void draw() {...} }
public abstract class Shape { public abstract double area(); public abstract double circumference(); } Exempel: abstrakt klass class Circle extends Shape { protected double r; protected static final double PI = 3.14; public Circle() {this(1.0);} public Circle(double r) {this.r = r;} public double area( {return PI * r * r;} public double circumference () {return 2 * PI * r;} } class Rectangle extends Shape { protected double w, h; public Rectangle (){this(0.0, 0.0);} public Rectangle (double w, double h) {this.w = w; this.h = h;} public double area() {return w * h;} public double circumference() {return 2 * (w + h);} }
Vektorer • Deklareras på följande sätt Typ[] vektor; • Instansiering (tex) vektor = new Typ[10] • Kan skapas från primitiva typer int[] tal = new int[5]; tal[0] = 2000; Sytem.out.println(tal[0]); • Kan skapas mer direkt Point[] punkter = {new Point(2, 3), new Point(56,72)}
... • Så kan vi skapa en vektor av Shapes Shape[] shapes = new Shape[3]; shapes[0] = new Circle(2.0); shapes[1] = new Rectangle(1.0, 2.0); shapes[2] = new Rectangle(10.0, 20.0); double totalArea = 0; for(int i = 0; i < shapes.length; i++) total_area += shapes[i].area();
Interface • Ett interface är som en abstrakt klass med enbart abstrakta metoder och konstanter public interface InterfaceX { public ReturTyp1 m1(X x); public ReturTyp2 m2(Y y); } • En klass kan deklarera att den implementerar ett eller flera interface • Observera att en klass endast är direkt subklass till en klass men att den kan implementera flera interface class MinFigur extends Figur implements Interface1, Interface2 { ...} • Ett interface kan utvidga ett eller flera andra interface public interface InterfaceN extends Interface1, Interface2, Interface3 {...}
public interface Sleeper { public void wakeUp(); public long ONE_SECOND = 1000; public long ONE_MINUTE = 60000; } public class GUIClock extends Applet implements Sleeper { . . . public void wakeUp() { repaint(); clock.letMeSleepFor(this, ONE_MINUTE); } } Exempel: interface Konstanter nås via Interfacenamn.konstant tex Sleeper.One_Second
..med interface med följande definitioner... public interface Drawable{ public void setColor(Color c); public void setPosition(Point p); public void draw(Window dw); } Rectangle public DrawableRectangle extends Rectangle implements Drawable{ private Color c; private Point pos; public void setColor(Color c) {this.c = c}; public void setPosition(Point p) {pos = p;} public void draw(Window dw) {dw.drawRect(pos.x, pos.y, height, width);} }
... så kan vi konstruera en vektor av interface (Givet att vi också konstruerat en DrawableCircle och en DrawableSquare på motsvarande sätt) Drawable[] drawables = new Drawable[3]; drawables[0] = new DrawableCircle(2.0); drawables[1] = new DrawableSquare(20.0); drawables[2] = new DrawableRectangle(10.0, 20.0); for(int i = 0; i < drawables.length; i++){ drawables[i].setPosition(i * 10.0, i * 5.0); drawables[i].draw(myWindow); }
Undantagshantering (eng. Exception handling) • Java är från början konstruerat med insikten om att fel uppkommer-ofta oväntade fel • Programmeraren skall alltid vara beredd att hantera ett fel • Därför ingår undantagshantering som en grundläggande mekanism i Java • En "exception" är en händelse som "stör" det normala programflödet och hindrar programmet från att fortsätta • Undantag kan vara av två olika modeller: • terminerande, dvs vi kan inte fortsätta från den punkt felet uppstod utan att åter anropa metoden som resulterade i felet • återupptagbar, vi kan fortsätta från avbrottspunkten (eventuellt med vissa data förändrade i felhanteringen) Java använder en terminerande modell
Exceptions • Hanterar situationer då fel har uppstått • Kan orsakas av fel koden inte klarar av att exekvera • tex division med noll • eller okontrollerbara fel hos externa enheter • tex filsystemet har gått ner eller annat fel i filhantering • Om något går fel • systemet signalerar ett avbrottsobjekt • Avbrottsobjektet letar sig upp i anropsstacken tills dess att en hanterare för det aktuella felet hittas. • try {//"normal" kod} • catch(Feltyp e) {//kod för att hantera felet}
Konsekvenser • Genom att använda exceptions kan vi först fokusera på att skriva koden för normalfallet • Först sedan tar vi hand om olika fel • Vi kan också (uniformt) hantera fel av grundläggande karaktär eller som sker i systemobjekt, som den virtuella maskinen • Ett fel som uppstår i en del av koden kan hanteras i en annan (där man förmodligen bättre vet hur lämplig hantering skall gå till) • Ett alternativ är att returnera null och sedan låta anropande rutin testa för detta fel • men vad händer om vi verkligen vill använda null som ett möjligt värde/resultat?
Javas exceptions • I Java kan en metod deklarera att den "kastar" ett exception • Användare av en sådan metod kan inte "glömma" att ta hand om ett sådant undantag utan är tvingade att skriva kod som hanterar felsituationen • Tar man inte hand om undantaget så säger kompilatorn ifrån • public void m() throws AktuelltUndantag {…} • try • { • //kod som använder metod som kastar AktuelltUndantag • } • catch(AktuellUndantag e) • {}
Exempel: fånga IOException try { File f = new File("exceptiontest1.result"); FileWriter w = new FileWriter(f); PrintWriter out = new PrintWriter(w); out.println("Det blev inga fel!"); out.println(); out.close(); } catch(IOException e) { System.err.println("Fel i filhantering"); }
Exempel: aritmetiskt fel int res, a = 10, b = 0; try { res = a / b; } catch(ArithmeticException e) { out.println(e); res = 1; } out.println("Efter felhantering är res: " + res);
... kan också fångas via generellare Exception try { res = a / b; } catch(Exception e) { out.println(e); // skriv ut info om felet res = 100; } out.println("Efter felhantering är res: " + res);} • ArithmeticException subklass till RuntimeException som är subklass till Exception
Felsignalerna bildar en hierarki Throwable Error LinkageError IncompatibleClassChangeError InstantiationError VirtualMachineError InternalError OutOfMemoryError StackOverflowError • Exception • IllegalAccessException • IOException • EOFException • FileNotFoundException • InterruptedIOException • MalformedURLException • RuntimeException • ArithmeticException • ClassCastException • EmptyStackException • IndexOutOfBoundsException • ArrayIndexOutOfBoundsException • StringIndexOutOfBoundsException • NegativeArraySizeException • NullPointerException • SecurityException
Skapa och signalera fel • Ny egen exception skapas som subklass till klassen Exception • Signalera fel med meddelandet throw • public class MyException extends Exception { • public MyException() {super();} • public MyException(String s) {super(s);} • } throw new MyException()
Exempel: throw package java.util public class Stack extends Vector { public Object push(Object item) {addElement(item); return item;} ... public synchronized Object peek() { int len = size(); if (len == 0) throw new EmptyStackException(); return elementAt(len - 1); } ...
Fånga flera fel • Vi kan fånga flera olika fel genom: • Vi kan använda finally om vi alltid vill utföra ett kodblock • try{...} • catch(ExceptionOne e1) {} • catch(ExceptionTwo e2) {} • catch(ExceptionThree e3) {} • try{...} • catch(SomeException e) {} • finally {//Gör alltid detta} • try{öppna fil} • catch(SomeException e) {felhantering} • finally{fil.close()}
Fler exempel try { int a[] = new int[2]; a[4]; } catch (ArrayIndexOutOfBoundsException e) { System.out.println("exception: " + e.getMessage()); e.printStackTrace(); } Argumentet givet då undantaget kastades Skriv information om felet på System.err
Deklarera att ett exception kastas • Vi kan i en metod deklarera att ett exception kastas • Eller flera samtidigt • public void myOpenFile() throws IOException {...} public File search(String s) throwsIOException, MyException1, MyException2 {...}
Vissa exceptions behöver man inte ta hand om, om man inte vill • Av praktiska skäl behöver man inte ta hand om exceptions som är subklasser till • Error • RuntimeException • Annars skulle man behöva ha exceptionhandling överallt • Varför?
Exempel: Throwtest // Några egna Exceptions. class MyException extends Exception { public MyException() {super(); } public MyException(String s) {super(s);} } class MyOtherException extends Exception { public MyOtherException() { super(); } public MyOtherException(String s) {super(s);} } class MySubException extends MyException { public MySubException() { super(); } public MySubException(String s) {super(s);} }
... public class throwtest { public static void main(String argv[]) { int i; try { i = Integer.parseInt(argv[0]); } catch (ArrayIndexOutOfBoundsException e) { // argv är tom System.out.println("Must specify an argument"); return; } catch (NumberFormatException e) { // argv[0] inte ett heltal System.out.println("Must specify an integer argument."); return; } a(i); }
... // Anropa b(), som är deklarerad att kasta ett visst exception. // Vi hanterar detta exception. public static void a(int i) { try { b(i); } catch (MyException e) { // Point 1. // Vi hanterar MyException och dess subklass MyOtherException if (e instanceof MySubException) System.out.print("MySubException: "); else System.out.print("MyException: "); System.out.println(e.getMessage()); System.out.println("Handled at point 1"); } }
…finally public static void b(int i) throws MyException { int result; try { System.out.print("i = " + i); result = c(i); System.out.print(" c(i) = " + result); } catch (MyOtherException e){ //Point 2 System.out.println("MyOtherException: " + e.getMessage()); System.out.println("Handled at point 2"); } finally { // Gör alltid en radframmatning. System.out.print("\n"); } }
... public static int c(int i) throws MyException, MyOtherException { switch (i) { case 0: throw new MyException("input too low"); case 1: throw new MySubException("input still too low"); case 99: throw new MyOtherException("input too high"); default: return i*i; } } VARNING! Case-satser bör egentligen undvikas i OO
Exempel på UML och Java (från Fii): lampa toggle Light1 off on # isOn : boolean + turnOn() : void + turnOff() : void + isOn() : boolean + toggle() : void + main(String []) : void toggle
… Light1, Javakod public class Light1 { protected boolean isOn; public void turnOn() {isOn = true;} public void turnOff() {isOn = false;} public boolean isOn() {return isOn;} public void toggle() {isOn = !isOn();} public static void main (String args[]) { Light1 light; light = new Light1(); System.out.println(light.isOn()); //ska ge false light.toggle(); System.out.println(light.isOn()); // ska ge true } }
Exempel: lampa2, med start i on-läge toggle off on toggle
... Light2, Javakod public class Light2 { // defultvärde för isOn kan anges vid deklarationen protected boolean isOn = true; // medlemsmetoderna som förut... public static void main (String args[]) { Light2 light; light = new Light2(); System.out.println(light2.isOn()); //true light.toggle(); System.out.println(light.isOn()); //false } }
Fler exempel på UML till kod • Vi ”översätter” diagram från tidigare föreläsningar till kod • Vi tittar speciellt på klass-, sekvens- och samarbetsdiagram från föreläsning 5
Javas API och paket • Om vi hinner (tveksamt...) så tittar vi på vad Javas olika paket kan erbjuda • Grundläggande klasser • Collections • Grafik • Socketar • RMI • osv