An Introduction to Programming and Object Oriented Design using Java 2nd Edition. May 2004 Jaime Niño Frederick Hosch Chapter 9 : Interfaces Objectives After studying this chapter you should understand the following: the role of abstraction in the specification of a server; the use of interfaces to specify servers independent of implementation details; the notion of subtype, and fundamental property of a subtype; contractual requirements in the implementation of an interface; multiple inheritance of interfaces; the notion and use of the strategy pattern. Also, you should be able to: specify and implement an interface; use an interface to capture commonality among similar classes. May 2004 NH-Chapter 9 1 Modeling alternative implementations Nim game implementation models class Player responsible for making a move according to Game rules. Strategies Player can implement when making a move: Timid strategy Greedy strategy Clever strategy May 2004 NH-Chapter 9 2 Modeling alternative implementations Player abstraction and Player clients should be independent of implementations; independent of strategies chosen; implementations must respect the abstraction’s contract: Player makes a move according to Game rules. May 2004 NH-Chapter 9 3 Java interfaces A Java interface is used to specify minimal functionality that a client requires of a server. A Java interface contains: method specifications, called abstract methods, and named constant definitions. A Java interface does not contain: constructors, method bodies, instance variables. May 2004 NH-Chapter 9 4 Player interface interface Player { public String name (); public int sticksTaken (); public void takeTurn int maxOnATurn); (Pile pile, } May 2004 NH-Chapter 9 5 Java interfaces An interface can be public , or package private. Method specifications in an interface are by default: public, and abstract (only specification with no implementation). May 2004 NH-Chapter 9 6 Java interface implementation A class implements an interface by naming interface in an implements clause in class heading, and including definitions for all methods in the interface. May 2004 NH-Chapter 9 7 Java interface implementation class TimidPlayer implements Player { public String name () { … } public int sticksTaken (){ … } public void takeTurn maxOnATurn) { … } (Pile pile, int } May 2004 NH-Chapter 9 8 Java interface implementation Static diagram display of relation between interface Player and class TimidPlayer «interface» Player TimidPlayer May 2004 NH-Chapter 9 9 Java interface Interface Player abstracts TimidPlayer, GreedyPlayer, and CleverPlayer «interface» Player is-a TimidPlayer May 2004 GreedyPlayer NH-Chapter 9 CleverPlayer 10 Interface and types An interface defines a type. A value is in the interface type if it references an instance of a class that implements the interface. A value of type reference-to-TimidPlayer, is also of type reference-to-Player. A value of type reference-to-GreedyPlayer, is also of type reference-to-Player. A value of type reference-to-CleverPlayer is also of type reference-to-Player. May 2004 NH-Chapter 9 11 Interface and types The type reference-to-TimidPlayer is said to be a subtype of the type reference-to-Player. The type reference-to-GreedyPlayer is said to be a subtype of the type reference-to-Player. The type reference-to-CleverPlayer is said to be a subtype of the type reference-to-Player. May 2004 NH-Chapter 9 12 Interface and types Reference-to-Player is a supertype of reference-to-TimidPlayer. reference-to-GreadyPlayer. reference-to-CleverPlayer. May 2004 NH-Chapter 9 13 Terminology Simplify terminology: refer to reference types by class or interface name. Thus we say “type Player” rather than “type reference-to-Player.” May 2004 NH-Chapter 9 14 Interfaces and types A type defined by an interface can be used like any other reference type. It can be the type of an instance variable or parameter, It can be the return type of a query. May 2004 NH-Chapter 9 15 Interfaces and types:Rewriting Game Can define class Game exactly as in Listing 8.3, even if Player is an interface and not a class. Instance variables can be of type Player: private Player player1; private player player2; constructors and methods can have Player parameters: public Game (Player player1, Player player2, int sticks) queries can return values of type Player: public () … May 2004 Player nextPlayer NH-Chapter 9 16 Types and Subtypes If client expects server of type Player, then a value of any Player subtype can be provided. Subtype rules: if type A is a subtype of type B, then an A value can be provided wherever a B value is required. an A expression can be writtenwherever a B value is required. May 2004 NH-Chapter 9 17 Types and Subtypes Thus for Game constructor: It can be specified with parameters of type Player interface; it can be invoked with arguments referencing TimidPlayers, GreedyPlayers, CleverPlayers. May 2004 NH-Chapter 9 18 Static types The Game method nextPlayer is specified as public Player nextPlayer () The Player whose turn is next. If game is a Game instance, Player is the static type of expression game.nextPlayer() May 2004 NH-Chapter 9 19 Dynamic types When game.nextPlayer() is evaluated during execution, value returned will reference an specific object: If an instance of TimidPlayer. Then dynamic type of value returned by expression is TimidPlayer. If an instance of GreedyPlayer. Then dynamic type of value returned by expression is GreedyPlayer. If an instance of CleverPlayer. Then dynamic type of value returned by the expression is CleverPlayer. The dynamic type is always a subtype of Player. May 2004 NH-Chapter 9 20 Types and Subtypes private Player nextPlayer; private void reportPlay (Player player) … public Player winner () … The following require expressions of type Player: nextPlayer = Player expression required; reportPlay(Player expression required); public Player winner () { … return Player expression required; } May 2004 NH-Chapter 9 21 Types and Subtypes Given: TimidPlayer timid = new TimidPlayer("Wakko"); The following are legal:: nextPlayer = timid; reportPlay(timid); public Player winner () { … return timid; } May 2004 NH-Chapter 9 22 Types and Subtypes If game is a Game instance, we cannot write the following: TimidPlayer next = game.nextPlayer(); Assignment operator requires a TimidPlayer on the right. game.nextPlayer() is of type Player, and Player is not a subtype of TimidPlayer. May 2004 NH-Chapter 9 23 Types and Subtypes p1 = tp Player p1; Player p2; TimidPlayer tp = new TimidPlayer("Wakko"); CleverPlayer cp = new cp CleverPlayer("Guy");CleverP layer p2 p1 Tim idPlayer tp cp p2 = cp CleverPlayer p2 p1 Tim idPlayer tp cp p2 = p1 CleverPlayer p2 p1 Tim idPlayer tp May 2004 NH-Chapter 9 24 Types and Subtypes The following are not legal: tp = p1; cp = p2; cp = tp; May 2004 // p1 is not of type TimidPlayer // p2 is not of type CleverPlayer // tp is not of type CleverPlayer NH-Chapter 9 25 Revised Nim game Classes Pile and Game remain the same. Game constructors, methods, and instance variables are written in terms of type Player. NimTUI will still have instance variables of type Player: private Player player1; private Player player2; May 2004 NH-Chapter 9 26 Revised Nim game Initialization code will create specific kinds of players. public NimTUI () { this.player1 = new TimidPlayer("Player1"); this.player2 = new GreedyPlayer("Player2"); this.game = null; this.in = new BasicFileReader(); } May 2004 NH-Chapter 9 27 Implementing classes and contracts Client interface promises this interface requires this server delivers this server accepts this Server server class can be more conservative in what it delivers (stronger postconditions) than what is specified by the interface May 2004 NH-Chapter 9 server class can be more liberal in what it accepts (weaker preconditions) than what is specified by the interface 28 Interface Movable Gnome moves Movable Ring May 2004 «interface» Potion NH-Chapter 9 Sword 29 Interface Weapon Explorer wields Weapon Sword May 2004 «interface» Pen NH-Chapter 9 MissileLauncher 30 Multiple inheritance of interfaces «interface» «interface» Weapon Movable S word class Sword implements Weapon, Movable {…} May 2004 NH-Chapter 9 31 Interface extension Assume all weapons are movable: «inter face» Movable Ri ng Potion «i nterface» Weapon Sword Pen Mi ssl eLauncher interface Weapon extends Movable {…} May 2004 NH-Chapter 9 32 Extending more than 1 interface An interface can extend more than one interface. «interfac e» « inte rfac e» Data Input Da ta Output « interfac e» Da taIO interface DataIO extends DataInput, DataOutpu May 2004 NH-Chapter 9 33 Modifying Nim: user vs. computer Want same simple nim game and text-based user interface Want user to play against “the computer” rather than just watching the game. May 2004 NH-Chapter 9 34 Modifying Nim: user vs. computer need two different kinds of players. One player decides its own move; the other gets its move from an external source, the user. May 2004 NH-Chapter 9 35 Modifying Nim: user vs. computer Define two classes IndependentPlayer, and InteractivePlayer. Both classes implement interface Player. IndependentPlayer is specified exactly as the class Player was in Chapter 8. The InteractivePlayer, gets its move from a client. May 2004 NH-Chapter 9 36 Interactive player specifications class InteractivePlayer implements Player A player in the game simple nim that gets moves from a client. public InteractivePlayer (String name) Create a new InteractivePlayer with the specified name. ensure: this.name().equals(name) public String name () This InteractivePlayer’s name. public int sticksTaken () Number of sticks removed on this InteractivePlayer's most recent turn. Returns 0 if this InteractivePlayer has not yet taken a turn. ensure: this.sticksTaken() >= 0 May 2004 NH-Chapter 9 37 Interactive player specifications public void setNumberToTake (int number) Set number of sticks this InteractivePlayer takes on its next turn. require: number > 0 public void takeTurn (Pile pile, int maxOnATurn) Take a turn: remove sticks from specified Pile. maxOnATurn is maximum number of sticks a Player can remove on a turn. require: pile.sticks() > 0, maxOnATurn > 0 ensure: 1 <= this.sticksTaken() && this.sticksTaken() <= maxOnATurn && pile.sticks() == old.pile.sticks() this.sticksTaken() May 2004 NH-Chapter 9 38 Interactive player specifications User interface must also be modified. It creates an InteractivePlayer and a IndependentPlayer : private InteractivePlayer user; private IndependentPlayer computer; public NimTUI () { this.user = new InteractivePlayer("user"); this.computer = new IndependentPlayer("computer"); this.game = null; this.in = new BasicFileReader(); } May 2004 NH-Chapter 9 39 Modifying User interface Added a parameter to playGame indicating whether user wants to play first. private void playGame (int numberOfSticks, boolean userPlay if (userPlaysFirst) game = new Game (user, computer, numberOfSticks); else game = new Game (computer, user, numberOfSticks) while (!game.gameOver()) { game.play(); reportPlay(game.previousPlayer()); } reportWinner(game.winner()); } May 2004 NH-Chapter 9 40 User interface – model interaction How does user interface know when to get a play from user? user interface checks whose turn it is before invoking play; Need add a conditional to the play loop, while (!game.gameOver()) { if (game.nextPlayer().equals(user)) { int numberToTake = readNumberToTake(); user.setNumberToTake(numberToTake); } game.play(); reportPlay(game.previousPlayer()); } readNumberToTake readNumberOfSticks. May 2004 NH-Chapter 9 is similar to 41 User interface – model interaction Problem: user interface is more involved in play of the game. Want “dumb” user interface, as isolated from model as possible. Role of the user interface is to manage input and output: its knowledge about how the model works should be minimized. This alternative makes the user interface the model driver. May 2004 NH-Chapter 9 42 User interface – model interaction InteractivePlayer tells user interface it needs a move. This alternative requires that model be client to user interface. Don’t want the model dependent on user interface. User interface is properly client to the model. Common: client needs to know that server has reached some particular state. User interface (client) needs to know that model (server) has reached a state in which it needs input from the user. May 2004 NH-Chapter 9 43 User interface – model interaction InteractivePlayer must know the user interface. InteractivePlayer needs to notify an object when it is about to make a move. May 2004 NH-Chapter 9 44 Interface InteractiveController interface InteractiveController Models an object that needs to be informed when a InteractivePlayer is about to make a play. public void update (InteractivePlayer player) The specified InteractivePlayer is making a play. May 2004 NH-Chapter 9 45 Interface InteractiveController Before removing sticks from pile, InteractivePlayer notifies InteractiveController by invoking update. public void takeTurn (Pile pile, int maxOnATurn controller.update(this); … } May 2004 NH-Chapter 9 46 Case: interactive player takes turn Game InteractivePlayer InteractiveController Pile takeTurn update talk to the user setNumberToTake remove May 2004 NH-Chapter 9 47 Completing InteractivePlayer How does the InteractivePlayer know InteractiveController? Add one more method to InteractivePlayer: the public void register (InteractiveController control) Set InteractiveController this InteractivePlayer is to report to. This InteractivePlayer will notify it before taking its turn. May 2004 NH-Chapter 9 48 Class TUIController «interface» notifies I nteracti veController TUIControll er May 2004 InteractivePlayer providesMoves NH-Chapter 9 49 TUIController and Game TUIController must know maximum number of sticks that can be removed on user’s turn. Add the following method to the Game: /** * The maximum number of sticks that can be removed on * the next turn. Returns 0 if the game is over. */ public int maxOnThisTurn () { if (pile.sticks() < MAX_ON_A_TURN) return pile.sticks(); else return MAX_ON_A_TURN; } May 2004 NH-Chapter 9 50 NimTUI playGame TUIController is by the NimTUI when Game is created: private void playGame (int numberOfSticks, boolean userPlaysFirst) { if (userPlaysFirst) game = new Game (user, computer, numberOfSticks); else game = new Game (computer, user, numberOfSticks); new TUIController(user,game,in); while (!game.gameOver()) { game.play(); reportPlay(game.previousPlayer()); } reportWinner(game.winner()); } May 2004 NH-Chapter 9 51 The strategy pattern Looking player classes, note duplicated code. Only difference in TimidPlayer, GreedyPlayer, and CleverPlayer is body of takeTurn. Duplicate code is a prime cause headaches, avoid when possible. of maintenance Can reduce duplicate code in player classes. May 2004 NH-Chapter 9 52 The strategy pattern make Player a class and give Player a component that determines what move to make. Player May 2004 hasStrategy PlayStrategy NH-Chapter 9 53 Strategy pattern A Player will have an instance variable referencing a PlayStrategy, private PlayStrategy strategy; May 2004 NH-Chapter 9 54 Strategy pattern takeTurn delegates responsibility for determining how many sticks to take to PlayStrategy: public void takeTurn (Pile pile, int maxOnATurn) { int number = strategy.numberToTake(pile, maxOnATurn); pile.remove(number); sticksTaken = number; } May 2004 NH-Chapter 9 55 Strategy pattern PlayStrategy is an interface that can be implemented in various ways. Pl ayer hasStrategy PlayStrategy TimidStrategy May 2004 «interface» GreedyStrategy NH-Chapter 9 CleverStrategy 56 Strategy pattern We can implement TimidStrategy class TimidStrategy implements PlayStrategy { public void numberToTake (Pile pile, int maxOnATurn) { return 1; } } May 2004 NH-Chapter 9 57 Strategy pattern The easiest way to equip a Player with a PlayStrategy is to provide one as a constructor argument: public Player (String name, PlayStrategy strategy) Create a Player with the specified name and strategy May 2004 NH-Chapter 9 58 Strategy pattern Player’s strategy can be changed dynamically. Player’s strategy is fixed when the Player is created to be either a TimidPlayer, GreedyPlayer, or CleverPlayer. Include method to change Player’s strategy: public void setStrategy (PlayStrategy strategy) Set this Player’s strategy to the one specified. Ability to dynamically change object’s behavior is one reasons for using strategy pattern. May 2004 NH-Chapter 9 59 Casting Given variable definitions Player player; InteractivePlayer user; The assignment statement user = player; is not legal; even if we write Player player; InteractivePlayer user = new InteractivePlayer("Loui player = user; //legal user = player; // not legal. May 2004 NH-Chapter 9 60 Casting When certain of the dynamic type of a value, we can cast the expression to this type: (type)expression Thus we can write: user = (InteractivePlayer)player; A cast to a supertype is always safe. May 2004 NH-Chapter 9 61 Boolean operator instanceOf Boolean operator instanceof is used to determined the type of value an expression produces at run-time. expression instanceof type Returns true if expression evaluates to a value of the specified type. player instanceof InteractivePlayer Returns true if the variable player references an InteractivePlayer when the expression is evaluated. May 2004 NH-Chapter 9 62 Summary Introduced the fundamental notion of interface: It captures functional requirements of a server. Similar to a class, but includes no implementation. It is not instantiated to produce objects. To implement an interface, a class names interface in an implements clause, and implement all methods specifies. Many concrete classes can implement an interface. May 2004 NH-Chapter 9 63 Summary Also introduced the notion of subtyping: If class C implements an interface I, reference type defined by C is a subtype of type defined by I. An expression of type C can be written in any context requiring I. If a client requires services defined by interface I, an instance of class C can provide those services. May 2004 NH-Chapter 9 64 Summary Java’s type conformance rules are static: verified by the compiler from the program text. If A is a supertype of B, e1 is an expression of type A, e2 an expression of type B: Can write e2 in a context requiring a B value. Cannot write e in a context requiring a B value If certain that evaluating e delivers a B value at run-time, must cast e1 to the appropriate type: (B)e1. If not certain that e1 delivers a B value, can guard cast by using the operator instanceof. May 2004 NH-Chapter 9 65 Summary Studied situation in which a client needs to know when a server reaches some state. (The observer pattern). The client informs the server of its interest by invoking a server method (register). To keep the server as independent as possible from the client, the server knows the client through a minimal interface. When the server reaches the relevant state, it informs the client by invoking a client method (update). An example is the InteractivePlayer and InteractiveController May 2004 NH-Chapter 9 66 Summary Studied a second situation in which some behavior of an object is encapsulated in a component. The component is defined by an interface, and the object’s behavior can be changed dynamically by replacing the component. This is referred to as the strategy pattern, and was illustrated in the player-with-strategy example. May 2004 NH-Chapter 9 67
© Copyright 2024 Paperzz