Interfaces Java Interface Notes
Total Page:16
File Type:pdf, Size:1020Kb
Interfaces Interfaces & • What is an interface? Informally, it is a specification subtyping of how an agent interacts with the outside world • Java has a construct called interface which is Lecture 4 used formally for this purpose – an interface describes how a class interacts with its clients CS 2112 – Spring 2014 – method names, argument/return types, fields 2 Java interface Notes interface IPuzzle { • name of interface: void scramble(); IPuzzle int tile(int r, int c); • An interface is not a class! boolean move(char d); • a class implements – cannot be instantiated } this interface by – incomplete specification implementing class IntPuzzle implements IPuzzle { public instance public void scramble() {...} methods as • class header must assert implements I for Java to public int tile(int r, int c) {...} specified in the recognize that the class implements interface I public boolean move(char d) {...} } interface • the class may • A class may implement several interfaces: implement other class X implements IPuzzle, IPod {...} methods 3 4 Why an interface construct? Why an interface construct? • good software engineering • Lots of examples in Java – specify and enforce boundaries between different parts of a team project Map<String, Command> h • can use interface as a type = new HashMap<String, Command>(); – allows more generic code List<Object> t = new ArrayList<Object>(); – reduces code duplication Set<Integer> s = new HashSet<Integer>(); 5 6 Example of code duplication class Client{ IntPuzzle p1 = new IntPuzzle(); ArrayPuzzle p2 = new ArrayPuzzle(); • Suppose we have two implementations of puzzles: ...display(p1)...display(p2)... – class IntPuzzle uses an int to hold state public static void display(IntPuzzle p){ – class ArrayPuzzle uses an array to hold state for (int r = 0; r < 3; r++) for (int c = 0; c < 3; c++) Code duplicated System.out.println(p.tile(r,c)); because • Say the client wants to use both implementations } IntPuzzle – perhaps for benchmarking both implementations to pick the and best one public static void display(ArrayPuzzle p){ ArrayPuzzle – client code has a display method to print out puzzles for (int r = 0; r < 3; r++) are different for (int c = 0; c < 3; c++) System.out.println(p.tile(r,c)); • What would the method look like? } display } 7 8 One Solution ― Abstract Classes abstract class Puzzle { Observation abstract int tile(int r, int c); ... } • Two display methods are needed because class IntPuzzle extends Puzzle { IntPuzzle and ArrayPuzzle are different types, Puzzle public int tile(int r, int c) {...} code ... and parameter p must be one or the other } class ArrayPuzzle extends Puzzle { public int tile(int r, int c) {...} • but the code inside the two methods is identical! ... } – code relies only on the assumption that the object p has an instance method tile(int,int) public static void display(Puzzle p){ • Is there a way to avoid this code duplication? Client for (int r = 0; r < 3; r++) code for (int c = 0; c < 3; c++) System.out.println(p.tile(r,c)); }} 9 10 Another Solution ― Interfaces IPuzzle interface IPuzzle { int tile(int r, int c); ... } IntPuzzle ArrayPuzzle class IntPuzzle implements IPuzzle { Puzzle public int tile(int r, int c) {...} code ... } • interface names can be used in type declarations class ArrayPuzzle implements IPuzzle { – IPuzzle p1, p2; public int tile(int r, int c) {...} ... } • a class that implements the interface is a subtype of the interface type public static void display(IPuzzle p){ – IntPuzzle and ArrayPuzzle are subtypes of IPuzzle Client for (int r = 0; r < 3; r++) – IPuzzle is a supertype of IntPuzzle and ArrayPuzzle code for (int c = 0; c < 3; c++) System.out.println(p.tile(r,c)); }} 11 12 Extending a Class vs Interfaces IPuzzle IPod IRon Implementing an Interface • A class can Classes AClass BClass – implement many interfaces, but – extend only one class • Unlike classes, types do not form a tree! • To share code between two classes – a class may implement several interfaces – put shared code in a common superclass – an interface may be implemented by several classes – interfaces cannot contain code 13 14 Static vs Dynamic Types Example int i = 3, j = 4; • Every variable (more generally, every expression that denotes some kind of data) has a static* or compile- Integer x = new Integer(i+3*j-1); time type System.out.println(x.toString()); – derived from declarations – you can see it – known at compile time, without running the program • static type of the variables i,j and the expression i – does not change +3*j-1 is int • static type of the variable x and the expression • Every object has a dynamic or runtime type new Integer(i+3*j-1) is Integer – obtained when the object is created using new • static type of the expression x.toString() is – not known at compile time – you can’t see it String (because toString() is declared in the class Integer to have return type String) * Warning! No relation to Java keyword static • dynamic type of the object created by the execution of is 15 new Integer(i+3*j-1) Integer 16 Reference vs Primitive Types Why Both int and Integer? x: • Reference types • Some data structures work only with reference types – classes, interfaces, arrays ( ) (Integer) Hashtable, Vector, Stack, ... – E.g.: Integer int value: 13 String toString() ... • Primitive types are more efficient for (int i = 0; i < n; i++) {...} • Primitive types – int, long, short, byte, boolean, char, float, double x: 13 17 18 Upcasting Upcasting and Downcasting • Example of upcasting: • Applies to reference types only • Used to assign the value of an expression of one Object x = new Integer(13); (static) type to a variable of another (static) type – static type of expression on rhs is Integer – upcasting: subtype → supertype – static type of variable x on lhs is Object – downcasting: supertype → subtype – Integer is a subtype of Object, so this is an upcast • A crucial invariant: • static type of expression on rhs must be a subtype of If during execution, an expression E is ever evaluated static type of variable on lhs – compiler checks this and its value is an object O, then the dynamic type of O is a subtype of the static type of E. • upcasting is always type correct – preserves the invariant automatically 19 20 Downcasting Is the Runtime Check Necessary? • Example of downcasting: Yes, because dynamic type of object may not be known at compile time Integer x = (Integer)y; – static type of y is Object (say) void bar() { – static type of x is Integer foo(new Integer(13)); } – static type of expression (Integer)y is Integer String(“x”) – Integer is a subtype of Object, so this is a downcast void foo(Object y) { • In any downcast, dynamic type of object must be a int z = ((Integer)y).intValue(); ... subtype of static type of cast expression } • runtime check, ClassCastException if failure • needed to maintain invariant (and only time it is needed) 21 22 Upcasting with Interfaces Why Upcasting? • Java allows up-casting: IPuzzle p1 = new ArrayPuzzle(); • Subtyping and upcasting can be used to avoid code IPuzzle p2 = new IntPuzzle(); duplication • Puzzle example: you and client agree on interface • Static types of right-hand side expressions are IPuzzle ArrayPuzzle and IntPuzzle, resp. interface IPuzzle { void scramble(); • Static type of left-hand side variables is IPuzzle int tile(int r, int c); boolean move(char d); • Rhs static types are subtypes of lhs static type, so } this is ok 23 24 Solution Method Dispatch interface IPuzzle { int tile(int r, int c); public static void display(IPuzzle p) { ... for (int row = 0; row < 3; row++) } for (int col = 0; col < 3; col++) class IntPuzzle implements IPuzzle { System.out.println(p.tile(row,col)); Puzzle public int tile(int r, int c) {...} } code ... } class ArrayPuzzle implements IPuzzle { public int tile(int r, int c) {...} • Which tile method is invoked? ... } – depends on dynamic type of object p (IntPuzzle or ArrayPuzzle) public static void display(IPuzzle p){ – we don't know what it is, but whatever it is, we Client for (int r = 0; r < 3; r++) know it has a tile method (since any class that code for (int c = 0; c < 3; c++) System.out.println(p.tile(r,c)); implements IPuzzle must have a tile method) }} 25 26 Method Dispatch Note on Casting public static void display(IPuzzle p) { for (int row = 0; row < 3; row++) for (int col = 0; col < 3; col++) • Up- and downcasting merely allow the System.out.println(p.tile(row,col)); } object to be viewed at compile time as a different static type • Compile-time check: does the static type of p • Important: when you do a cast, either up (namely IPuzzle) have a tile method with or down, nothing changes the right type signature? If not error → – not the dynamic type of the object • Runtime: go to object that is the value of , p – not the static type of the expression find its dynamic type, look up its tile method • The compile-time check guarantees that an appropriate tile method exists 27 28 Another Use of Upcasting Java instanceof Heterogeneous Data Structures • Example: if (p instanceof IntPuzzle) {...} • Example: IPuzzle[] pzls = new IPuzzle[9]; • true if dynamic type of p is a subtype of pzls[0] = new IntPuzzle(); IntPuzzle pzls[1] = new ArrayPuzzle(); • expression pzls[i] is of type IPuzzle • usually used to check if a downcast will succeed • objects created on right hand sides are of subtypes of IPuzzle 29 30 Example Avoid Useless Downcasting • suppose twist is a method implemented void moveAll(IPuzzle[] pzls) { only in IntPuzzle for (int i = 0; i < pzls.length; i++) { if (pzls[i] instanceof IntPuzzle) void twist(IPuzzle[] pzls) { bad ((IntPuzzle)pzls[i]).move("N"); else ((ArrayPuzzle)pzls[i]).move("N"); for (int i = 0; i < pzls.length; i++) { }} if (pzls[i] instanceof IntPuzzle) { IntPuzzle p = (IntPuzzle)pzls[i]; p.twist(); } void moveAll(IPuzzle[] pzls) { } for (int i = 0; i < pzls.length; i++) } good pzls[i].move("N"); } 31 32 Coercions Subinterfaces • Sometimes Java will let you use a type as if it were another type but does an • Suppose you want to extend the interface to implicit coercion/conversion to the target include more methods type.