290 likes | 407 Views
Übung Softwareentwicklung 2 für Wirtschaftsinformatik. UE03 Polymorphismus, Dynamic Binding. Kennedy: "Don’t ask what the country can do for you, ask what you do for your country" "Don’t ask what you can do for your objects, ask what your objects can do for you". Polymorphism.
E N D
Übung Softwareentwicklung 2für Wirtschaftsinformatik UE03Polymorphismus, Dynamic Binding
Kennedy: "Don’t ask what the country can do for you, ask what you do for your country" "Don’t ask what you can do for your objects, ask what your objects can do for you" SE2UE_00 - 2
Polymorphism • Polymorphic = “of many forms” • Webster's Dictionary about "polymorphic" • the quality or state of being able to assume different forms as: a : existence of a species in several forms independent of the variations of sex b : the property of crystallizing in two or more forms with distinct structure • A polymorphic method is one that has the same name for different classes of the same family but has different implementations for the various classes SE2UE_00 - 3
Overloading methods & Constructors • Overloading refers to the ability to allow different methods or constructors of a class to share the same name • If two methods or constructors in the same class have different signatures, then they may share the same name MethodSignature void move(int x, int y) move(int, int) void move(double x, double y) move(double, double) boolean move(int x, int y) move(int, int) • Methods of different classes can have the same signature SE2UE_00 - 4
a constructor with a different signature a method with a different signature An example - Point class class Point { private double x, y; public Point() { x = 0.0; y = 0.0; } public Point(double x, double y) { this.x = x; this.y = y; } public double distance(Point other) { double dx = this.x - other.x; double dy = this.y - other.y; return Math.sqrt(dx * dx + dy * dy); } public double distance(double x, double y) { double dx = this.x - x; double dy = this.y - y; return Math.sqrt(dx * dx + dy * dy); } } SE2UE_00 - 5
Example … cont. • when an overloaded method is called, the number and the types of the arguments are used to determine the method that will be invoked … … Point p1 = new Point(); Point p2 = new Point(20.0, 30.0); p2.distance(p1); p2.distance(50.0, 60.0) … … SE2UE_00 - 6
Circle Square Subtypes • A subclass is a specialization of its superclass • Every instance of the subclass is an instance of the superclass • The type defined by the subclass is a subtype of the type defined by its superclass Shape Shape Circle Square SE2UE_00 - 7
Circle and Square are subclasses of Shape Rule of Subtype • A value of a subtype can appear wherever a value of its supertype can appear • If class E extends class B, any instance of E can act as an instance of B class Shape { … … } class Circle extends Shape { … … } class Square extends Shape { … … } Shape shape1, shape2; shape1 = new Circle(); shape2 = new Square(); SE2UE_00 - 8
Static vs dynamic binding • Binding refers to the association of a method invocation and the code to be executed on behalf of the invocation. • In static binding (early binding), all the associations are determined at compilation time. • conventional function calls are statically bound • In dynamic binding (late binding), the code to be executed in response to a method invocation (i.e., a message) will not be determined until runtime. • method invocations to reference variable shapeArray[i] (in the following example) are dynamically bound SE2UE_00 - 9
Polymorphism • The ability of different objects to perform the appropriate method in response to the same message is known as polymorphism • The selection of the appropriate method depends on the class used to create the object name getName( ) calculateArea( ) Shape radius calculateArea( ) side calculateArea( ) Circle Square SE2UE_00 - 10
a generic action Example // Object-Oriented Programming and Java, // Danny C.C. Poo and Derek B.K. Kiong, Springer, 1998) // To illustrate the concept on dynamic binding, // overriding and overloading class Shape { private String name; public Shape(String aName) { name=aName; } public String getName( ) { return name; } public float calculateArea( ) { return 0.0f; } } // End Shape class SE2UE_00 - 11
inheritance overloading overriding Example … cont., class Circle extends Shape { private float radius; public Circle(String aName) { super(aName); radius = 1.0f; } public Circle(String aName, float radius) { super(aName); this.radius = radius; } public float calculateArea() { return (float)3.14f*radius*radius; } } // End Circle class class Square extends Shape { private float side; public Square(String aName) { super(aName); side = 1.0f; } public Square(String aName, float side) { super(aName); this.side = side; } public float calculateArea() { return (float) side*side; } } // End Square class SE2UE_00 - 12
rule of subtype dynamic binding Example … cont., public class ShapeDemoClient { public static void main(String argv[ ]) { Shapec1 = new Circle("Circle C1"); Shapec2 = new Circle("Circle C2", 3.0f); Shapes1 = new Square("Square S1"); Shapes2 = new Square("Square S2", 3.0f); Shape shapeArray[] = {c1, s1, c2, s2}; for (int i = 0; i < shapeArray.length; i++) { System.out.println("The area of " + shapeArray[i].getName() + " is " + shapeArray[i].calculateArea() + " sq. cm."); } } // End main } // End ShapeDemoClient1 class SE2UE_00 - 13
Polymorphism • Polymorphism is possible because of • inheritance: subclasses inherit attributes and methods of the superclass. public class Circle extends Shape { … … } • method overriding: subclasses can redefine methods that are inherited from the superclass public class Shape { public float calculateArea( ) { return 0.0f; } … … } public class Circle extends Shape { public float calculateArea( ) { return (float) 3.14f*radius*radius; } … … } SE2UE_00 - 14
Polymorphism • rule of subtype: reference variables of superclass can be used to refer object instances of its subclasses Shape c = new Circle(“Circle C”); Shape s = new Square(“Square S”); Shape shapeArray[ ] = {c, s, … }; • dynamic binding: method invocations are bound to methods during execution time for(int i = 0; i < shapeArray.lenth; i++) shapeArray[i].calculateArea() ; Circle shapeArray Square c s Square Triangle Rectangle SE2UE_00 - 15
Incremental development • adding new class is made easy with inheritance and polymorphism name getName( ) calculateArea( ) Shape base height calculateArea( ) Circle Square Triangle SE2UE_00 - 16
no change on for loop Example class Triangle extends Shape { private float base, height; public Triangle(String aName) { super(aName); base = 1.0f; height = 1.0f; } public Triangle(String aName, float base, float height) { super(aName); this.base = base; this.height = height; } public float calculateArea() { return (float) 0.5f*base*height; } } // End Triangle class public class ShapeDemoClient { public static void main(String argv[ ]) { … … Shapet = new Triangle(“Triangle T”, 4.0f, 5.0f); Shape shapeArray[ ] = {c1, s1, c2, s2, t}; for (int i = 0; i < shapeArray.length; i++) { System.out.println("The area of " + shapeArray[i].getName() + " is " + shapeArray[i].calculateArea() + " sq. cm.");} } // End main } // End ShapeDemoClient class extension of array by one triangle SE2UE_00 - 17
Increased code readability • polymorphism also increases code readability since the same message is used to call different objects to perform the appropriate behavior. versus alternative really bad style! for (i = 0; i < numShapes; i++) switch (shapeType[i]) { ‘c’: calculateCircleArea( … … ); break; ‘s’: calculateSquareArea( … … ); break; } for(int i = 0; i < shapeArray.lenth; i++) shapeArray[i].calculateArea( ); for (Shape s : shapeArray) { s.calculateArea(); } much better style! SE2UE_00 - 18
Design Hints • use polymorphism, not type information whenever you find the code of the form if (x is of type 1) action1(x); else if (x is of type 2) action2(x); action( ) XType action( ) XType1 XType2 action( ) x.action( ) SE2UE_00 - 19
Design Hints • move common behavior to the superclass • to flood fill a shape means to do the following: - plot the outline of the shape - if it isn’t a closed shape, give up - find an interior point of the shape - fill the shape • these common behaviors can be put into the superclass Shape: abstract class Shape { … … public boolean floodfill(GraphicsPanel aPanel, Color aColor) { plot(aPanel); if ( ! isClosed( ) ) return false; Point aPoint = center( ); aPanel.fill(aPoint.getX( ), aPoint.getY( ), aColor); return true; } } SE2UE_00 - 20
Design Hints • subclasses merely need to redefine: plot( ), isClosed( ), and center( ). Floodfill( ) plot( ) isClosed( ) center( ) Shape plot( ) isClosed( ) center( ) Circle Square Triangle Shape c = new Circle(”Circle C”); Shape s = new Square(”Square S”); Shape t = new Triangle(”Triangle T”); Shape shapeArray[ ] = {c, s, t} … … for (int i = 0; i < shapeArray.length; i++) shapeArray[i].floodfill(aPanel, aColor); … … SE2UE_00 - 21
Selbsttest • Angenommen die Klasse Bird hat eine Methode fly() und es gibt eine davon abgeleitete Klasse Ostrich(Strauß), deren Objekte nicht fliegen können sollen.Was kann man da tun? • ... die Methode fly mit einer leeren Methode überschreiben (oder man wirft in dieser Methode eine CannotFly-Exception) • ... zwei neue Klassen einführen: eine für Laufvögel (RunningBird) und eine für Flugvögel (FlyingBird), wobei nur FlyingBird eine Methode fly hat. Die Basisklasse von beiden ist Bird (ohne fly) SE2UE_00 - 22
Selbsttest • Welche Methodenaufrufe erfordern dyn. Bindung? Wo ist stat. Bindung möglich? class B extends A { B () { this(3); } // 1) B (int x) { super(x); } // 2) void k (int f) { o(); // 3) super.k(f - 1); // 4) A a = new B(); B b = new B(); a.m(); // 5) b.m(); // 6) } final void m () { ... } } 1) statisch: es gibt nur einen möglicher Konstruktor (der zwar überladen, aber nicht überschrieben ist) 2) statisch: nur ein möglicher Konstruktor (in der Superklasse) vorhanden 3) dynamisch: Methode o kann in einer abgeleiteten Klasse überschrieben sein 4) statisch: Supercalls sind immer statisch gebunden, da es nur eine Methode gibt, die damit gemeint sein kann. 5) dynamisch: die Methode m der Klasse A kann überschrieben sein (ist sie auch, von der Methode m in der Klasse B) 6) statisch: die Methode m der Klasse B kann nicht überschrieben sein, da sie final ist und der stat. Typ B den dyn. Typ von b auf B oder davon abgeleitet einschränkt – also kein A möglich. SE2UE_00 - 23
Selbsttest • Welche Methodenaufrufe erfordern dyn. Bindung? Wo ist stat. Bindung möglich? 7) statisch: statische Methode abstract class A { A () { ... } A (int y) { ... } void k (int a) { l(); // 7) m(); // 8) n(); // 9) o(); // 10) } static void l () { ... } abstract void m (); private void n () { ... } void o () { ... } } 8) dynamisch: siehe Punkt 5 9) statisch: die Methode könnte zwar von einer inneren Klasse überschrieben worden sein (Java gibt aber dem private Vorrang und bindet statisch, d.h. private wird prinzipiell statisch gebunden). 10) dynamisch: siehe Punkt 3 SE2UE_00 - 24
Selbsttest • Welche Arten von inneren Klassen gibt es? Wozu kann man diese verwenden? • Statische innere Klassen haben keine Referenz auf das umgebende (äußere) Objekt (Outer.Inner inner = new Outer.Inner();). z.B. für Knoten einer Liste, wenn die Knoten keine Referenz auf die Liste selbst benötigen. • Nicht-statische innere Klassen haben eine Referenz auf das umgebende (äußere) Objekt (Outer.Inner inner = outer.new Inner();). z.B. zur Simulation von Mehrfachvererbung. • Lokale innere Klassen werden in einer Methode deklariert:void foo() { class MyClass extends OtherClass { void m() {…} }; OtherClass my = new MyClass(); my.m();}Sie können statisch oder nicht-statisch sein (je nach umgebender Methode). z.B. Ersatz von Methoden-Referenzen, Ersatz von lokalen (nur in dieser Methode benötigten) Methoden. • Anonyme innere Klassen sind im Prinzip das gleiche wie lokale innere Klassen, jedoch ohne der Klasse einen speziellen Namen zu geben (=> Kein Konstruktor möglich)void foo() { OtherClass my = new OtherClass() { void m() {…} }; my.m();} SE2UE_00 - 25
Abstract Class • Eine abstrakte Klasse ist eine Klassendefinition von der keine Instanzen gebildet werden können;dh. AbstractClass o = new AbstractClass() ist nicht erlaubt! • Eine abstrakte Klasse hat mindestens eine oder mehrere abstrakte Methoden (abstract method) = d.h. die Realisierung der Methoden ist nicht "vollstaendig". • Subklassen können von einer abstrakten Klasse abgeleitet sein und können wiederum abstrakt sein. • Nur von "konkreten" (d.h. nicht abstrakten Subklassen) können Instanzen gebildet werden. Diese müssen noch alle "fehlenden" Methoden implementieren. • Eine abstrakte Klasse kann (wie jede Klasse) als Typ verwendet werden; d.h. AbstractClass o = new ConcreteClass() ist erlaubt. • Eine abstrakte Methode sowie eine abstrakte Klasse werden durch das Schlüsselwort "abstract" ausgezeichnet. SE2UE_00 - 26
Abstract Class abstract class GraphicObject { int x, y; // konkrete Attribute ... void moveTo(int newX, int newY) { ... // konkrete Methode } abstract void draw(); // nur gesagt, dass jedes // GraphicObject eine Methode draw() können muss } // Jede nicht-abstrakte Sub-Klasse muss eine Implementierung für // die Methode draw() zur Verfügung stellen. class Circle extends GraphicObject { void draw() { ... // konkrete Implementierung } } class Rectangle extends GraphicObject { void draw() { ... // konkrete Implementierung } } SE2UE_00 - 27
Beispiel: Shapes • Eine abstrakte Klasse Shape mit den zwei Spezialisierungen Rectangle und Circle soll modelliert werden. Geben Sie die nötigen Attribute der Klassen an und implementieren Sie die Methoden move und draw.Hinweis: Zum Zeichnen können Sie die Klasse Graphics verwenden:class Graphics { static void drawRect(int x, int y, int w, int h) { . . . } static void drawCircle(int x, int y, int r) { . . . } } • Gegeben Sei eine Klasse ShapeList: class ShapeList { private Shape[] shapes; ... }Implementieren Sie je eine Methode zum Zeichnen (drawAll()) und zum Verschieben (moveAll()) aller Shapes in der Liste. SE2UE_00 - 28
Beispiel: Shapes • public abstract class Shape { protected int x, y; public Shape(int x, int y) { this.x = x; this.y = y; } public abstract void draw(); public void move(int dx, int dy) { x += dx; y += dy;}} • public class Circle extends Shape { protected int r; public Circle(int x, int y, int r) { super(x, y); this.r = r; } public void draw() { Graphics.drawCircle(x, y, r); }} • public class Rectangle extends Shape { protected int w, h; public Rectangle(int x, int y, int w, int h) { super(x, y); this.w = w; this.h = h; } public void draw() { Graphics.drawRect(x, y, w, h); }} • public class ShapeList { private Shape[] shapes; ... public drawAll() { for(int i=0; i<shapes.length; i++) shapes[i].draw(); } public moveAll(int x, int y) { for(int i=0;i<shapes.length;i++) shapes[i].move(x,y); }} SE2UE_00 - 29