Interfaces and Sub-Typing Interfaces Java Interface Notes
Total Page:16
File Type:pdf, Size:1020Kb
Interfaces Interfaces • So far, we have talked about interfaces informally in the ordinary English sense of and the word. Sub-typing – “interface to a class tells the client how to obtain the functionality implemented in that class” • Java has a construct called interface which can be used formally for this purpose – and for doing some other really cool things… Java interface Notes Class IntPuzzle implements IPuzzle{ • Interface itself cannot be instantiated. interface IPuzzle{ …… void scramble(); public void scramble(){ – incomplete specification int tile(int r, int c); …..} • It is not enough for a class to just have implementations public int tile(int r, int c){ boolean move(char d); of interface methods; class header must also assert } …..} public boolean move(char d){ “implements I” for Java to recognize that the class …..} implements interface I. } • A class may implement several interfaces. • Name of interface: IPuzzle – (eg) class X implements IPuzzle, IRaq { • A class can implement this interface by implementing public instance methods with the names and type ……} signatures specified in the interface. • The class may implement other methods. 1 Example of code duplication Why interface construct? • Suppose we have two implementations of puzzles: • One use of interfaces: software engineering – Class IntPuzzle uses an int to hold state – specifying and enforcing boundaries between – Class ArrayPuzzle uses an array to hold state different parts of a team project, as in Puzzle • Assume client wants to use both implementations in code example. – perhaps for benchmarking both implementations to pick • But interfaces can do much more. the best one? – Interfaces let you write more “generic” code – client code has a display method as always to print out puzzles that reduces code duplication. • What would the display method look like? Class Client{ IntPuzzle p1 = new IntPuzzle(); Observation ArrayPuzzle p2 = new ArrayPuzzle(); ….display(p1)…display(p2)… • Two display methods are needed because types public static void display(IntPuzzle p){ IntPuzzle and ArrayPuzzle are different, and for (int r = 0; r < 3; r++) parameter p must have one type or the other. for (int c = 0;c<3;c++) { System.out.print(p.tile(r,c)); • Ironically, the code inside the two methods is Code duplicated System.out.print(‘ ‘); identical. because types }} – Code relies only on assumption that parameter p is passed IntPuzzle and public static void display(ArrayPuzzle p){ an object that has an instance method tile(int,int). ArrayPuzzle for (int r = 0; r < 3; r++) are different. • Is there a way to avoid this code duplication? for (int c = 0;c<3;c++) { System.out.print(p.tile(r,c)); – Use interfaces and sub-typing System.out.print(‘ ‘); }} } 2 Interfaces as types Note IPuzzle Interfaces: IPuzzle IRan IRaq IntPuzzle ArrayPuzzle Classes: AClass BClass • Name of an interface can be used as a variable type. – (eg) IPuzzle p1, p2; • Class that implements the interface is said to be a sub-type of • Since a class can implement several interfaces, it the interface type. may have many super-types. – IntPuzzle and ArrayPuzzle are sub-types of IPuzzle. • Interface is said to be a super-type of those classes. • An interface can be implemented by several – IPuzzle is a super-type of type IntPuzzle and ArrayPuzzle. classes, so it may have many sub-types. Names, Objects and Types Paradox with interfaces as types • In programming languages, like in real life, • We cannot instantiate an interface I. we attribute type both to names (variables) – Interface is a partial specification. and to objects. • If we cannot create objects of type I, why bother • Example from real life: gender permitting interface names to be types? – Two types: Male and Female – (eg) IPuzzle p1,p2; – These types are assigned to people (objects): – Fine, but what would we ever assign to p1 and p2?!! • The President of Cornell is a Male. • To understand this, let us look at a real-life • The Provost of Cornell is a Female. analogy. – These types are also assigned to names: • Male George, Sam, Helmut, Bubba; • Female Rie, Naomi, Indira, Melanie; 3 Sub-typing in real life Unisex names Human Male Female • Some names can refer to people of either gender: • Let us add a new type called Human. • Humans have certain functionalities: (eg): Sandy, Pat, Jackie – They walk upright. • How do we fit unisex names into our – They have juxtaposed thumbs. – They are intelligent…. classification? • Male and female are sub-types of type Human because they implement this functionality although in different • Here is an idea…. ways. • Like an interface, type Human cannot be instantiated directly: every human must be either a male or a female. Sub-types and subsets Human Back to names Male Female Male Female Human • Using these types, we can now give types to Sub-types Subsets unisex names as well: • Male George, Sam, Helmut, Bubba; • Sub-types and subsets are distinct concepts. • Female Rie, Naomi, Indira, Melanie; • Sub-types are characterized by some common • Human Jo, Sandy, Pat; functionality. – Sub-type female in our example is characterized by ability to give birth. • In this example, a mixture of males and females is a subset of type human, but it is not a sub-type. 4 Naming people Up-casting • Simple picture without sub-typing: • Situation is a little more complex with unisex names (sub-typing). – Male objects get male names. – Female objects get female names. • Example: Sandy = new Female(); – Type of reference returned by RHS is Female. •Examples: – Type of LHS name is Human. //we created a new male object and named it George – Nevertheless, no type error because Female is sub-type George = new Male(); //type checks of Human. //give object named Sam the alias Bubba • Up-casting: type of RHS reference is sub-type of Bubba = Sam; //type checks type of LHS name. //give object named Bubba the alias Melanie • Up-casting is always type-correct. Melanie = Bubba;//type mismatch • Example: Sandy = Laura; • In last example, we do not need to know anything about – You do not need to know the object named Laura to who Bubba is to see that there is a type mismatch. determine that the assignment is type-correct. Down-casting Resolution of paradox with • Is this type-correct? Bubba = Sandy; interfaces as types • Answer: depends. • Java allows up-casting: – Type of RHS name (reference) Sandy is Human which is super-type of LHS name – IPuzzle p1 = new ArrayPuzzle(); – Type of object named Sandy: either Male or Female – IPuzzle p2 = new IntPuzzle(); – Whether or not the assignment is legal depends not on the •Note: type of the RHS reference but on the type of the actual object. – Type of reference returned by right-hand side • Down-casting: Type of LHS name is sub-type of RHS expression of first statement is ArrayPuzzle. reference. – Type of variable on left-hand side is IPuzzle. • Down-casting may or may not be legal – Two types are different, but type of rhs reference is a – need to look at object to determine legality sub-type of type of the variable. 5 Your code Why up-casting? Class IntPuzzle implements IPuzzle{ • Sub-typing and up-casting allow you to avoid …scramble()…tile()…move()…twist() code duplication in many situations. } • Puzzle example: you and client agree on interface Class ArrayPuzzle implements IPuzzle{ IPuzzle. ……scramble()...tile()…move()… } interface IPuzzle{ void scramble(); Class IntPuzzle implements a method called twist int tile(int r, int c); which is not a method of interface IPuzzle. boolean move(char d); } Client Code Method execution public static void display(IPuzzle p){ Class Client{ for (int r = 0; r < 3; r++) IntPuzzle p1 = new IntPuzzle(); for (int c = 0;c<3;c++) { ArrayPuzzle p2 = new ArrayPuzzle(); System.out.print(p.tile(r,c)); ….display(p1)…display(p2)… Up-casting: System.out.print(‘ ‘); Objects of type IntPuzzle }} public static void display(IPuzzle p){ and ArrayPuzzle are for (int r = 0; r < 3; r++) passed to parameter of • Subtle point: which tile method is invoked in code shown for (int c = 0;c<3;c++) { type IPuzzle. above? System.out.print(p.tile(r,c)); – tile method in IntPuzzle class?? System.out.print(‘ ‘); • What if object passed in is of type ArrayPuzzle? }} – tile method in ArrayPuzzle class?? } • What if object passed in is of type IntPuzzle? – tile method in IPuzzle interface?? • Huh?? • To understand this, let us look again at execution model. 6 Program area IntPuzzle: ..scramble..tile…move… ArrayPuzzle:..scramble..tile..move.. Resolving the name “p.tile” Heap • Stack frame for invocation of display has storage for variables p,r,c. Stack IntPuzzle • Suppose method is passed an IntPuzzle object in parameter p as shown. c i: ArrayPuzzle r i: • Invocation “p.tile(r,c)” in body of display is p IPuzzle: scramble executed as discussed earlier: tile scramble – Look up method tile in object O referenced by p. move tile – Invoke that method passing it this (object O),r,c. move – In our example, therefore, we would invoke the tile method implemented in the IntPuzzle class. Note on type-checking Think public static void display(IPuzzle p){ • Type of paramater p: IPuzzle for (int r = 0; r < 3; r++) – IPuzzle itself does not have a tile method! for (int c = 0;c<3;c++) { • Actual method that gets invoked is implemented System.out.print(p.tile(r,c)); sometimes in the ArrayPuzzle class and System.out.print(‘ ‘); sometimes in the IntPuzzle class! }} • Dynamic method binding: • Compile-time check: does type of reference p (IPuzzle) – Name “p.tile” is not resolved to a single method. have a method called tile with the right type signature? If – In different invocations, name may be resolved to not, error. different methods. • Runtime: go into object referred to by p and look up its tile • Method display is sometimes said to be a method.