Presentation is loading. Please wait.

Presentation is loading. Please wait.

Introduction to Computer Science Classes and Methods I »Objects »Instance Methods »Formal Parameters, the Stack, Call-by-Value, Scope of Variables, Mutable.

Similar presentations


Presentation on theme: "Introduction to Computer Science Classes and Methods I »Objects »Instance Methods »Formal Parameters, the Stack, Call-by-Value, Scope of Variables, Mutable."— Presentation transcript:

1 Introduction to Computer Science Classes and Methods I »Objects »Instance Methods »Formal Parameters, the Stack, Call-by-Value, Scope of Variables, Mutable vs. Immutable Classes »Object Variables as References (i.e., addresses) »Example: Encapsulation Tic-tac-toe board Unit 7

2 7- 2 Once Again, With Feeling We have already seen some examples of objects, instance variables, and instance methods The purpose of this section is to go over the concepts in much more detail, to learn new things about objects and their use, and to see examples of their use

3 7- 3 An Object is a Collection of Attributes and Operations An object encapsulates data values within a single entity, along with operations to be performed on those data values An object’s behavior is often general enough to be reused in multiple situations Classes, the basis of objects, provide the basis for deriving other classes through inheritance

4 7- 4 The Structure of Classes class name { declarations constructor definitions method definitions } instance variables and symbolic constants how to create and initialize objects how to manipulate those objects These parts of a class can actually be in any order

5 7- 5 Methods First Two kinds of methods: Class methods and Instance methods Math.sqrt is an example of a Class method; “Math” is the name of a class, and we invoke the sqrt method in that class main is also a Class method I’m still not going to talk more about Class methods now; only Instance methods in this lecture

6 7- 6 Methods Calling Methods Each method contains a sequence of statements to be executed When a method f( ) calls a method g( ), Java begins executing the statements of g( ) but remembers that it was in the middle of f( ) When g( ) is done, Java returns to the executing f( ), continuing where it left off

7 7- 7 Methods Calling Methods: Execution is Nested void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } void g ( ) { System.out.println(“A!”); System.out.println(“B!”); System.out.println(“C!”); System.out.println(“D!”); }

8 7- 8 Of Course, Nesting can be to Multiple Levels void e ( ) {...... obj.f( );... } 1 3 2 4 5 6 8 7 9 A key point is that Java remembers where it was, and resumes execution there when returning from a method call

9 7- 9 Methods Returning Values Some methods return a value ( int, double, boolean, etc.) A method that returns a value can be used wherever Java wants a value of that type (e.g., in an expression) wage = sinp.readInt( ); Use the statement return value; to return a value from a method, where the value is of the appropriate type

10 7- 10 Method Not Returning a Value Other methods do not return a value, i.e., they return type void A call to a method that returns no value constitutes a complete Java statement bill.printTime( ); Use the statement return; to return from a void method, or you can just let the method execute until the end, and it will automatically return

11 7- 11 Formal Parameters The heading of a method specifies the return type, and the identifier and type of each parameter to the method These identifiers are called the formal parameters of the method When the method is called, the call supplies the actual parameters (or arguments) of the call

12 7- 12 Formal Parameters of a Method boolean checkValue (int col, int row, int limit) returned type of method name of method three formal parameters of method, each of type int Call to checkValue( ) (as an expression): bill.checkValue(3, 7, 9) assigns 3, 7, and 9 to the formal parameters col, row, and limit, respectively; then executes the method

13 7- 13 Matching Arguments and Formal Parameters bill.checkValue(3, 7, 9) boolean checkValue (int col, int row, int limit) { if (row > limit)... else... } There must be an (exact) match between the number, order, and type of the actual parameters and the formal parameters (except for things like an int value being automatically converted to a double).

14 7- 14 Legal? double findValue (int start, double end, int limit) bill.findValue(3, 5.0, 9) bill.findValue(5.0, 3, 9) bill.findValue(5, 3, 9) bill.findValue(5, 3) bill.findValue(5, 3, 9, 4) bill.findValue(x, y, z)

15 7- 15 Local Variables Instance methods can also have local variables, defined within the method (in addition to the class attributes) These variables store values during the method’s execution boolean checkValue (int col, int row, int limit) { double d; if (row > limit)... }

16 7- 16 Class Abstraction The most important stage in writing a class is to get an abstraction of the class done first. –What does an object of this type represent? –What is its interface? –What is its internal state? This means you have to know what should be the internal state (variables) and also the behavior/interface (methods) of the class before you start to write your class code.

17 7- 17 Objects and Classes The relationship between Classes and Objects can be seen as the relationship between a blueprint/model and the actual object built from it. –Example: Blueprint of a house (class) and the house (object) The class defines: –The type of data that will be held in an object –The code for the methods of the object In order to use a class you must instantiate an object from it. –This corresponds to building the house from the blueprint –There may be many objects from a single class

18 7- 18 An Example Class The Time class will be used to create objects the represent a time (hour and minute) within a day It comes with methods for creating and manipulating hours and minutes It has two internal integers, _hour (between 0 and 23), and _minute (between 0 and 59) _hour _minute Time addMinutes( int m ) void printTime( ) Time

19 7- 19 Class Abstraction! The Time class will be used to create objects the represent a time (hour and minute) within a day –What does an object of this type represent? It comes with methods for creating and manipulating hours and minutes –What is its interface? It has two internal integers, _hour (between 0 and 23), and _minute (between 0 and 59) –What is its internal state?

20 7- 20 Conventions… We will use an underscore before the name of a variable that belongs to the class (as opposed to a local variable that belongs to a method): _hour _minute This is “just” a Java convention, but stick to it, for everyone’s sake…

21 7- 21 The Time objects The objects themselves, created from the Time class, can hold values for _hour and _minute _hour _minute Time addMinutes( int m ) void printTime( ) Time bill Attributes: _hour = 7 _minute = 18 Methods: Time addMinutes(int m) void printTime ( ) scott Attributes: _hour = 14 _minute = 41 Methods: Time addMinutes(int m) void printTime ( )

22 7- 22 The Time Class’s Interface A method that adds m minutes to an existing Time object’s time, returning a new Time object with the new time Time addMinutes(int m) A method that prints the value of a Time object void printTime( ) A constructor, for creating and initializing a Time object Time (int h, int m)

23 7- 23 Encapsulation The internal state of an object is not directly accessible to other parts of the program Other parts of the program can only access the object using its interface We say that the state is encapsulated or hidden This gives modularity to the program addMinutes(int m) printTime()............ _hour _minute

24 7- 24 Encapsulation Hiding what’s inside the object is a big part of Object Oriented Programming Programming projects get complicated You can only hold (7 plus or minus 2) facts at a time in your brain Break the big problem into individual objects that each works as a “black box”

25 7- 25 Not Just a Pretty Interface You are told to implement the Time class Your boss tells you what the class’s interface is; there’s another group (in San Jose) that’s building the rest of the program, and they will use the Time class that you build The details of what goes on inside the class are hidden The important thing is: the San Jose group doesn’t need to know about the implementation of Time, only its interface!

26 7- 26 Clients and Classes Methods that use the Time class are called clients of the class To keep roles clear, both clients and classes have certain rights This is a “division of labor”

27 7- 27 Rights of a Class Define the public interface of the class Hide any and all private details of implementation Protect internal, private data from access by a client To change the implementation details at any time, provided the public interface stays the same

28 7- 28 You Get to “Fine-Tune” the Encapsulation The private modifier specifies an identifier that is only visible within the class. Usually used for fields (instance variables) of the class. The public modifier specifies an identifier that is accessible to all other classes. Usually used for methods.

29 7- 29 Rights of a Client To declare variables of the class type To create instances (objects) of the class, using the class constructors To send messages to instances of the class by invoking the instance methods defined by the class To know the public interface of the class To know which instance methods alter the instance

30 7- 30 The Structure of the Time Class Definition class Time { declarations public Time (int h, int m) {... } public Time addMinutes (int m) {... } public void printTime ( ) {... } } constructor definition method definition

31 7- 31 API Documentation Your classes are often intended to be used by other programmers Programmers that use your class are not interested in the way it is implemented. They want to use it as a whole and are only interested in what it does and how to use it. API (Application Programmer Interface) documentation is a description of the interface of the class intended for the application programmer who wants to use it. To use the class, we need not (and should not) look at the code. All that is needed is the class API.

32 7- 32 API Documentation The JDK contains a special tool for the generation of API documentation for your classes, called javadoc. Any documentation which is part of the interface begins with /** (double asterisk) and ends with */ javadoc takes as input Java programs and automatically generates documentation using: –the public/protected method signatures –the documentation comments (enclosed by /** … */ ). The output is an HTML file which can be viewed by an internet browser.

33 7- 33 class Clock API Documentation /** * A clock represents a point of time in a 12 * hour period within a precision of seconds. * Its range: 1:00:00 -- 12:59:59. */ public class Clock { private int _hours; private int _minutes; private int _seconds; /** * Constructs a Clock: Sets the clock to the * specified time. */ public Clock(int hours, int minutes, int seconds){ //… }

34 7- 34 Clock API Documentation – continued /** * Constructs a Clock: Sets the clock to 12:00:00 */ public Clock(){ this(12,0,0); } /** * Advances this clock by 1 second. */ public void secondElapsed() { //… } //…

35 7- 35 Javadoc Process.java file.html file javadoc View using a browser

36 7- 36 Clock javadoc – page 1

37 7- 37 Clock javadoc – page 2

38 7- 38 What should you comment? You should put a documentation comment for the class itself and for any member of the class which is part of its interface All public constructors and methods should have documentation comments Private methods are not part of the interface of the class, thus javadoc skips them. (But you should still comment them for internal purposes.) In the rare cases that there are public fields, they should have documentation comments

39 7- 39 API Documentation Remember that documentation comments are written for programmers who use your class as a whole. They should describe only –What the class does; –How to use it. Documentation comments should not describe how a class is implemented. Documentation comments should be –Short and descriptive; –Written in a simple language (ENGLISH); –Accurate. Assume that the reader doesn’t know anything about your class

40 7- 40 API Documentation Tags Documentation comments can also include tagged paragraphs that give a standard way to document several features of the interface such as method parameters, return values, etc. A tagged paragraph begins with the symbol @ followed with a tag keywords. Tags: @see, @author, @version, @param, @return, @exception. Documentation comments text can include HTML tags.

41 7- 41 @param tag /** * Changes the current time to hour:minute:second * @param hours The new hour value. * @param minutes The new minutes value. * @param seconds The new seconds value. */ public void setTime(int hours, int minutes, int seconds) { this.hours = hours; this.minutes = minutes; this.seconds = seconds; }

42 7- 42 setTime generated javadoc

43 7- 43 @return /** * Returns the current hour * @return The current hour (between 1 and 12). */ public void getHour() { return hours; }

44 7- 44 getHour javadoc

45 7- 45 Naming The names you use for your class and for its public methods are part of the class API Good descriptive naming is crucial for a clear API General rules about naming: –Follow the Java conventions –Use descriptive names –Do not use abbreviations! –Make names long enough, but not unnecessarily long –Consists of words in English with no abbreviations –Use a dictionary Read the style guidelines!

46 7- 46 The Structure of the Time Class Definition class Time { declarations public Time (int h, int m) {... } public Time addMinutes (int m) {... } public void printTime ( ) {... } } constructor definition method definition

47 7- 47 Creating a Time Object As you know: Time dawn; dawn = new Time(5, 35); or, all at once, Time dawn = new Time(5, 35); declaration creation and assignment

48 7- 48 What’s Really Happening? When we declare a variable of a simple type, we actually get a location in memory to store the value: int temperature; gives us: temperature

49 7- 49 What’s Really Happening? When we declare a variable of an object type, we get a reference in memory to an object (the object’s address); the object is stored elsewhere: Time dawn = new Time(5, 35); gives us: dawn the heap dawn Attributes: _hour = 5 _minute = 35 Methods: Time addMinutes(int m) void printTime ( )

50 7- 50 What’s Happening Behind the Scenes? We just talked about object variables and how they “point” to an object in the heap Let’s look at what’s going on in the computer’s memory, behind the scenes You don’t handle this yourselves, Java does. But it helps (e.g., understanding parameter passing) if you understand what is going on

51 7- 51 What’s All This I Hear About “Pointers”? Timelunchtime = new Time(12, 0), dinnertime = new Time(0, 0); lunchtime Attributes: _hour = 12 _minute = 0 Methods: … dinnertime Attributes: _hour = 0 _minute = 0 Methods: …

52 7- 52 Object Variable Contains Object’s Address in the Heap An object variable represents the address, in computer memory, of an object. dinnertime Attributes: _hour = 0 _minute = 0 Methods: … heap

53 7- 53 Object Variable Contains Object’s Address in the Heap dinnertime Attributes: _hour = 0 _minute = 0 Methods: … 32476 heap An object variable represents the address, in computer memory, of an object.

54 7- 54 Thanks for the Memory When we declare simple variables inside the computer, memory is set aside: int totalMinutes, days; double temperature; [1247][1248][1249][1250][1251][1252][1253][1254] undefined totalMinutes temperature days Part of the Computer’s Memory:

55 7- 55 Thanks for the Memory Notice that –Different types of simple variables might take up different amounts of memory –Each variable has an “address” in memory But Java handles all this automatically [1247][1248][1249][1250][1251][1252][1253][1254] undefined totalMinutes temperature days

56 7- 56 Thanks for the Memory An ordinary variable names its piece of memory; an assignment to the variable changes the value stored there; we make assignments to it: totalMinutes = 43; days = 12; temperature = 98.6; [1247][1248][1249][1250][1251][1252][1253][1254] undefined 43 12 98.6 totalMinutes temperature days

57 7- 57 What Happens with Object Variables When an object variable is declared: –the computer sets aside a memory location to hold the (eventual) address of the object Time lunchtime; [1247][1248][1249][1250][1251][1252][1253][1254] undefined 43 12 98.6 totalMinutes temperature days lunchtime

58 7- 58 What Happens with Pointers When an object is created and assigned: –the computer sets aside enough memory in the heap to hold the appropriate object –the address that marks the object location in the heap is given to the object variable lunchtime = new Time(12, 0); [1247][1248][1249][1250][1251][1252][1253][1254] undefined 43 12 98.6 totalMinutes temperature days lunchtime 27193

59 7- 59 What Happens with Pointers [1247][1248][1249][1250][1251][1252][1253][1254] undefined 43 12 98.6 totalMinutes temperature days lunchtime Attributes: _hour = 12 _minute = 0 Methods: … 27193 heap

60 7- 60 What Happens with Pointers [1247][1248][1249][1250][1251][1252][1253][1254] undefined 43 12 98.6 totalMinutes temperature days lunchtime Attributes: _hour = 12 _minute = 0 Methods: … heap Sometimes I’ll draw it this way

61 7- 61 What’s Really Happening (again)? When we declare a variable of an object type, we get a reference in memory to an object (the object’s address); the object is stored elsewhere: Time dawn = new Time(5, 35); gives us: dawn the heap dawn Attributes: _hour = 5 _minute = 35 Methods: Time addMinutes(int m) void printTime ( )

62 7- 62 Using the Object’s Methods OK, so now we’ve created dawn The constructor has initialized the object with the values _hour=5 and _minute=35 We have two methods at our disposal: –addMinutes( ), which takes an integer argument and returns a new Time object –printTime( ), which takes no arguments and prints the time

63 7- 63 Object Operations Time dusk = dawn.addMinutes(60 * 12); dusk.printTime( ); These two simple Java statements actually cause a large number of actions. “ Time dusk ” declares a new Time object “ dawn.addMinutes(60 * 12) ” creates a new reference to a Time object, which is then assigned to “ dusk ” “ dusk.printTime( ); ” sends dusk the message to print its value

64 7- 64 dawn.addMinutes(60 * 12) dawn Attributes: _hour = 5 _minute = 35 Methods: Time addMinutes(int m) void printTime ( ) addMinutes(60 * 12)

65 7- 65 dawn ’s addMinutes( ) Method Creates a New Time Object (it must have used a constructor) dawn Attributes: _hour = 5 _minute = 35 Methods: Time addMinutes(int m) void printTime ( ) Attributes: _hour = 17 _minute = 35 Methods: Time addMinutes(int m) void printTime ( ) (it still has no name since it isn’t assigned to any variable)

66 7- 66 Then This New Object is Assigned to the Time Variable dusk Time dusk = dawn.addMinutes(60 * 12); dawn Attributes: _hour = 5 _minute = 35 Methods: Time addMinutes(int m) void printTime ( ) Attributes: _hour = 17 _minute = 35 Methods: Time addMinutes(int m) void printTime ( ) dusk

67 7- 67 Then dusk is Sent the printTime( ) Message, and Does its Thing dusk Attributes: _hour = 17 _minute = 35 Methods: Time addMinutes(int m) void printTime ( ) printTime( ) dusk.printTime( ); (and it prints “5:35PM”)

68 7- 68 Let’s Write a Program That’s a Client of the Time Class We want the following output: 8:30AM ____________________ 9:00AM ____________________ 9:30AM ____________________ 10:00AM ___________________

69 class Schedule { public static void main (String[ ] args) { Time start = new Time(8, 30); start.printTime( ); System.out.println(“ ____________________”); start = start.addMinutes(30); start.printTime( ); System.out.println(“ ____________________”); start = start.addMinutes(30); start.printTime( ); System.out.println(“ ____________________”); start = start.addMinutes(30); start.printTime( ); System.out.println(“ ____________________”); } }

70 7- 70 One Class Making Use of an Outside Class The class Schedule must be in a file called Schedule.java The class Time must be in a file called Time.java Both must be compiled (although the Java compiler will handle the second compilation automatically)

71 7- 71 Assignments The only new part of the program is the assignment, to the object variable start, the result of the addMinutes(30) message: start = start.addMinutes(30); Let’s look at what’s going on.

72 7- 72 Creation of Time Object start Time start = new Time(8, 30); start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( )

73 7- 73 start.addMinutes(30) start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) addMinutes(30)

74 7- 74 start ’s addMinutes( ) Method Creates a New Time Object (it must have used a constructor) start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) Attributes: _hour = 9 _minute = 0 Methods: Time addMinutes(int m) void printTime ( ) (it still has no name since it isn’t assigned to any variable)

75 7- 75 Then This New Object is Assigned to the Time Variable start start = start.addMinutes(30); start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) Attributes: _hour = 9 _minute = 0 Methods: Time addMinutes(int m) void printTime ( ) start (the old Time object is thrown away, automatically)

76 7- 76 The Time Class Isn’t that wonderful? We were able to use the class Time, without having any idea about how it was implemented Now, let’s see what that class Time might actually look like inside

77 class Time { private int _hour, _minute; public Time (int h, int m) { _hour = h; _minute = m; } public Time addMinutes (int m) { int totalMinutes = ((60*_hour) + _minute + m) % (24*60); if (totalMinutes < 0) totalMinutes = totalMinutes + (24*60); return new Time(totalMinutes/60, totalMinutes%60); } CONTINUED ON NEXT SLIDE

78 public void printTime ( ) { if ((_hour == 0) && (_minute == 0)) System.out.print(“midnight”); else if ((_hour == 12) && (_minute == 0)) System.out.print(“noon”); else { if (_hour == 0) System.out.print(12); else if (_hour>12) System.out.print(_hour-12); else System.out.print(_hour); if (_minute < 10) System.out.print(“:0”+_minute); else System.out.print(“:” + _minute); if (_hour < 12)System.out.print(“AM”); elseSystem.out.print(“PM”); } } } end of class Time

79 7- 79 private int _hour, _minute; Declares two integer attributes for objects created from class Time The modifier “ private ” means that the instance variables _hour and _minute can be used by methods inside the class Time (i.e., by objects that have those methods); they are not usable outside the class

80 7- 80 private int _hour, _minute; The modifier “ public ” would mean the variables could be accessed and modified by methods outside the class Good object oriented programming makes instance variables private ; a well-designed program should rarely need public instance variables

81 7- 81 Constructors Constructors tell Java how to initialize new objects of the class It’s a method, but a special one –Has the same name as the class –Has no return type (not even void ) Constructors are declared private or public (usually public, of course) Often takes arguments that are used in initializing the object public Time (int h, int m) { _hour = h; _minute = m; }

82 7- 82 Method Definitions Definition headers tell what the method returns, and what its arguments are Both are declared public, meaning they can be called by clients of the class A class must have some public methods; often all the methods and the constructor are public, but if you want a method that will only be used internally to objects of the class, you can declare such a method private public Time addMinutes (int m) { … } public void printTime ( ) { … }

83 7- 83 Using Your Own Instance Variables Notice that when a method, like addMinutes( ) or the Time( ) constructor, wants to use its own instance variables (_hour and _minute), it can just mention their names (no object necessary) class Time { private int _hour, _minute; public Time (int h, int m) { _hour = h; _minute = m; } public Time addMinutes (int m) { int totalMinutes =((60*_hour) +_minute + m)%(24*60); if (totalMinutes < 0) totalMinutes = totalMinutes + (24*60); return new Time(totalMinutes/60, totalMinutes%60); }

84 7- 84 Overloaded Constructors Sometimes its useful to be able to create new objects in multiple ways (using different numbers or types of arguments to the constructor) Java allows you to define multiple constructors, as long as you give them different numbers or types of arguments in the definitions (so Java will know which one you meant)

85 7- 85 Example of Additional Constructors class Time { private int _hour, _minute; public Time (int h, int m) { _hour = h; _minute = m; } public Time ( ) { _hour = 0; _minute = 0; } public Time (int m) { _hour = m/60; _minute = m%60; } public Time addMinutes (int m) { … } public void printTime ( ) { … } }

86 7- 86 How to Use Them With these new constructors, the declarations: Timet1 = new Time( ), t2 = new Time(720), t3 = new Time(525); are equivalent to: Timet1 = new Time(0, 0), t2 = new Time(12, 0), t3 = new Time(8, 45);

87 7- 87 One Method Calling Another Method Inside the Same Object Let’s create a new method to put into the Time class Let’s call it subMinutes, where bill.subMinutes(i) gives the same results as bill.addMinutes(-i)

88 7- 88 Implement by Using addMinutes( ) public Time subtractMinutes (int m) { return receiverobject.addMinutes(-m); } Who is the receiverobject? When we’re defining the method in the class, we don’t yet know who the object is Like in the robot world, the receiver can be left out, and the object “talks to itself”

89 7- 89 But who is the “move” a Message To? The messages will be sent by an instance of the MileWalker class to itself ! class MileWalker extends BasicRobot { void moveMile { move; move; move; move; move; move; move; move; } } Remember?

90 7- 90 subtractMinutes( ) public Time subtractMinutes (int m) { return addMinutes(-m); } bill is an object of type Time client sends bill.subtractMinutes(n) subtractMinutes( ) generates a message to bill of addMinutes(-n)

91 7- 91 bill = bill.subtractMinutes(18); bill Attributes: _hour = 13 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) subtractMinutes(18)

92 7- 92 subtractMinutes(18) generates a message addMinutes(-18) bill Attributes: _hour = 13 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) addMinutes(-18)

93 7- 93 bill’s addMinutes( ) Method Creates a New Time Object bill (it still has no name since it isn’t assigned to any variable) bill Attributes: _hour = 13 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) Attributes: _hour = 13 _minute = 12 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m)

94 7- 94 Then This New Object is Assigned to the Time Variable bill bill Attributes: _hour = 13 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) Attributes: _hour = 13 _minute = 12 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) (the old Time object is thrown away, automatically) bill

95 7- 95 Let’s put another method into the class Time Compare two times to see whether the first is “prior to” the second (assuming they’re in the same day) t2 Attributes: _hour = h2 _minute = m2 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) boolean priorTo (Time t) Attributes: _hour = h1 _minute = m1 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) boolean priorTo (Time t) t1 ?<?< True if h1 < h2, or h1 = h2 and m1 < m2

96 7- 96 We need to have access to hour and minute of both objects public boolean priorTo (Time t) { return ((_hour < t’s hour) || ((_hour == t’s hour) && (_minute < t’s minute))); } There are two objects: a receiving object (that gets the priorTo( ) message), and the argument object (t) “_hour”, “_minute” are the receiving object’s hour and minute (simply uses the variables’ names) How do we get to the argument object’s _hour and _minute?

97 7- 97 Access to an Object’s Instance Variables Hey, wait a second! Those variables were private in the definition of the class Time! How can they be accessed by another object? public boolean priorTo (Time t) { return ((_hour < t._hour) || ((_hour == t._hour) && (_minute < t._minute))); }

98 7- 98 Encapsulation is not Among Instances of Same Class Encapsulation is to protect programmers, and is thus between the code of different classes Sometimes object instances of the same class need to access each other’s “guts” (e.g., for state copying – if we want to create an identical instance of an object we have)

99 7- 99 private int _hour, _minute; The modifier “private” means that the instance variables _hour and _minute can be used by methods inside the class Time (i.e., by objects that have those methods); they are not usable outside the class A method of class C can see the instance variables of objects of type C other than the receiver, using dot notation

100 7- 100 One More Method to Put in the Class Time Let’s define boolean after(Time t), which gives the opposite of priorTo (kind of) The receiver object checks to make sure that the argument object t is later than the receiver What’s wrong with this? public boolean after (Time t) { return !priorTo(t); }

101 7- 101 Not Quite Right public boolean after (Time t) { return !priorTo(t); } Above returns true if the two objects are equal (since priorTo( ) returns false in that case); we want after( ) to return false if the two objects are equal; so switch the objects: public boolean after (Time t) { return t.priorTo( receiver of this message ); }

102 7- 102 We need to refer to the object that received the message In subtractMinutes( ), we got around the problem by sending a message with no receiver specified This worked, as Java took the “current object” as the one who would get the message But now we need to send the name of the “current object” as an argument, and we don’t know what the object will be named (when we are defining the class Time)

103 7- 103 this Java gives us “this” as a variable within an instance method that refers to the actual object that receives the message It’s a variable, but it never needs to be declared (we just get it implicitly) Solution is: public boolean after (Time t) { return t.priorTo(this); }

104 7- 104 What’s going on public boolean after (Time t) { return t.priorTo(this); } Attributes: _hour = 13 _minute = 30 Methods:... Attributes: _hour = 13 _minute = 12 Methods:... second first after(second) priorTo(first)

105 7- 105 public boolean after (Time t) { return t.priorTo(this); } When the Class is Defined, these names are not known Attributes: _hour = 13 _minute = 30 Methods:... Attributes: _hour = 13 _minute = 12 Methods:... second first after(second) priorTo(this) “this” stands for “first” the client wrote “first.after(second)” here is t

106 7- 106 The Structure of the Time Class Definition class Time { private int _hour, _minute; public Time (int h, int m) {_hour = h; _minute = m;} public Time addMinutes (int m) {... } public void printTime ( ) {... } public Time subtractMinutes (int m) { return addMinutes(-m); } public boolean priorTo (Time t) { return ((_hour < t._hour) || ((_hour == t._hour) && (_minute < t._minute))); } public boolean after (Time t) { return t.priorTo(this); } } constructor definition declarations of class attributes 5 method definitions

107 7- 107 We’ve Seen How Nested Method Calls Work void e ( ) {...... obj.f( );... } 1 3 2 4 5 6 8 7 9 A key point is that Java remembers where it was, and resumes execution there when returning from a method call

108 7- 108 A Stack Handles Nesting Let’s improve the way we think about this nesting When method e( ) calls method f( ), which calls method g( ), we can think of a “stack of methods” Like putting a piece of paper on top of another piece on top of another piece... the topmost piece is the method being executed now, the others we’ll return to Each piece of paper holds the parameters and local variables

109 7- 109 Starting Execution in main( ) Method main( ) STACK public static void main (String[ ] args) {......... obj.e();... } top

110 7- 110 Call to method e( ) Method e( ) Where we came from: main, line 4 Method main( ) STACK void e ( ) {...... obj.f( );... } public static void main (String[ ] args) {......... obj.e();... } top

111 7- 111 Executing method e( ) Method e( ) Where we came from: main, line 4 Method main( ) STACK void e ( ) {...... obj.f( );... } public static void main (String[ ] args) {......... obj.e();... } top

112 7- 112 Call to method f( ) Method e( ) Where we came from: main, line 4 Method main( ) STACK Method f( ) Where we came from: e, line 3 void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } top

113 7- 113 Executing method f( ) Method e( ) Where we came from: main, line 4 Method main( ) STACK Method f( ) Where we came from: e, line 3 void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } top

114 7- 114 Call to method g( ) Method e( ) Where we came from: main, line 4 Method main( ) STACK Method f( ) Where we came from: e, line 3 Method g( ) Where we came from: f, line 4 top void g ( ) { System.out.println(“A!”); System.out.println(“B!”); System.out.println(“C!”); System.out.println(“D!”); } void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } void e ( ) {...... obj.f( );... } main (String[ ] args) {......... obj.e();... }

115 7- 115 Method g( ) finishes, the stack has its top removed void g ( ) { System.out.println(“A!”); System.out.println(“B!”); System.out.println(“C!”); System.out.println(“D!”); } void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } void e ( ) {...... obj.f( );... } main (String[ ] args) {......... obj.e();... } Method e( ) Where we came from: main, line 4 Method main( ) STACK Method f( ) Where we came from: e, line 3 top

116 7- 116 Method f( ) finishes, the stack has its top removed void g ( ) { System.out.println(“A!”); System.out.println(“B!”); System.out.println(“C!”); System.out.println(“D!”); } void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } void e ( ) {...... obj.f( );... } main (String[ ] args) {......... obj.e();... } Method e( ) Where we came from: main, line 4 Method main( ) STACK top

117 7- 117 Method e( ) finishes, the stack has its top removed void g ( ) { System.out.println(“A!”); System.out.println(“B!”); System.out.println(“C!”); System.out.println(“D!”); } void f ( ) { System.out.println(“Hi there!”); System.out.println(“Nice weather!”);... obj.g( ); System.out.println(“That was fun!”); System.out.println(“Time to move on!”); } void e ( ) {...... obj.f( );... } main (String[ ] args) {......... obj.e();... } Method main( ) STACK top

118 7- 118 Variables are held on the stack, too When we put items on the stack, we also write down –values of parameters –local variables Let’s look at the class Schedule, to see how the program actually executes and keeps track of variables with the stack

119 7- 119 Executing Schedule Method main( ) STACK top class Schedule { public static void main (String[ ] args) { Time start = new Time(8, 30); start.printTime( ); System.out.println(“ ____________________”); start = start.addMinutes(30);... } } args: ? start: ? heap

120 7- 120 Creation of Time object “start” Method main( ) STACK class Schedule { public static void main (String[ ] args) { Time start = new Time(8, 30); start.printTime( ); System.out.println(“ ____________________”); start = start.addMinutes(30);... } } args: ? start: start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) heap top

121 7- 121 Sending object “start” the printTime() message Method main( ) STACK class Schedule { public static void main (String[ ] args) { Time start = new Time(8, 30); start.printTime( ); System.out.println(“ ____________________”); start = start.addMinutes(30);... } } args: ? start: start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) heap Method printTime( ) Came from: main, line 2 this: top

122 7- 122 printTime() finishes, the stack is popped Method main( ) STACK class Schedule { public static void main (String[ ] args) { Time start = new Time(8, 30); start.printTime( ); System.out.println(“ ____________________”); start = start.addMinutes(30);... } } args: ? start: start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) heap top

123 7- 123 Later…the message addMinutes(30) is sent to “start” Method main( ) STACK args: ? start: start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) heap Method addMinutes( ) Came from: main, line 4 this: m: 30 totalMinutes: ? public Time addMinutes (int m) { int totalMinutes = ((60*_hour) + _minute + m) % (24*60);... } top

124 7- 124 addMinutes( ) initializes totalMinutes Method main( ) STACK args: ? start: start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) heap Method addMinutes( ) Came from: main, line 4 this: m: 30 totalMinutes: 540 public Time addMinutes (int m) { int totalMinutes = ((60*_hour) + _minute + m) % (24*60);... } top

125 7- 125 addMinutes creates new Time object and returns it Method main( ) STACK args: ? start: start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) heap Attributes: _hour = 9 _minute = 0 Methods: Time addMinutes(int m) void printTime ( ) top

126 7- 126 main assigns returned value to start Method main( ) STACK args: ? start: Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) heap Attributes: _hour = 9 _minute = 0 Methods: Time addMinutes(int m) void printTime ( ) start top

127 7- 127 Let’s Try it Again What if we had the same program, but instead of the message addMinutes(30), we had the message subtractMinutes(10)? class Schedule2 { public static void main (String[ ] args) { Time start = new Time(8, 30); start.printTime( ); System.out.println(“ ____________________”); start = start.subtractMinutes(10);... } }

128 7- 128 The message subtractMinutes(10) is sent to “start” Method main( ) STACK args: ? start: start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) heap Method subtractMinutes() Came from: main, line 4 this: m: 10 public Time subtractMinutes (int m) { return addMinutes(-m); } top

129 7- 129 subtractMinutes( ) generates an addMinutes( ) message to the same object Method main( ) STACK args: ? start: Method subtractMinutes() Came from: main, line 4 this: m: 10 Method addMinutes( ) Came from: subtractMinutes, line 1 this: m: -10 totalMinutes: ? public Time addMinutes (int m) { int totalMinutes = ((60*_hour) + _minute + m) % (24*60);... } start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) heap top

130 7- 130 addMinutes( ) initializes totalMinutes public Time addMinutes (int m) { int totalMinutes = ((60*_hour) + _minute + m) % (24*60);... } start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) heap Method main( ) STACK args: ? start: Method subtractMinutes() Came from: main, line 4 this: m: 10 Method addMinutes( ) Came from: subtractMinutes, line 1 this: m: -10 totalMinutes: 500 top

131 7- 131 addMinutes( ) creates new Time object and returns it to subtractMinutes( ) Method main( ) STACK args: ? start: Method subtractMinutes() Came from: main, line 4 this: m: 10 start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) heap Attributes: _hour = 8 _minute = 20 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) top

132 7- 132...which returns it to main( )... Method main( ) STACK args: ? start: start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) heap Attributes: _hour = 8 _minute = 20 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) top

133 7- 133 …which assigns it to Time variable “start” Method main( ) STACK args: ? start: Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) heap Attributes: _hour = 8 _minute = 20 Methods: Time addMinutes(int m) void printTime ( ) Time subtractMinutes(int m) start (garbage, thrown away) top

134 7- 134 Call-by-value Parameters are passed into methods in Java in a straightforward way They are copied into the formal parameters of the method, like an assignment statement would do This kind of parameter passing is known as call-by-value

135 7- 135 Java passes parameters using call-by-value bill.checkValue(3, 7, 9) boolean checkValue (int col, int row, int limit) { if (row > limit)... else... } col is assigned 3 row is assigned 7 limit is assigned 9

136 7- 136 Even When Simple Variables are Involved With call-by-value, col gets a copy of what's in x, row gets a copy of what's in y, limit gets a copy of what's in z Right after we return from checkValue, there's not going to have been any change to the values of x, y, z – guaranteed x = 3; y = 7; z = 9; bill.checkValue(x, y, z); boolean checkValue (int col, int row, int limit) {... }

137 7- 137 Java passes parameters using call-by-value Nothing unusual seems to be happening here However, there are consequences of call-by-value, both for simple type parameters, as well as for object type parameters Let’s explore the issues

138 7- 138 I Can See Clearly Now If you understand what is going on with addresses, the operations in Java between object variables and during parameter passing become completely clear Ready?

139 7- 139 Start with Regular Assignment to a Simple Variable When we are dealing with simple variables, assignment takes the contents of the right-hand side and puts in the left-hand side variable: temperature = 98.6; totalMinutes = 43; days = totalMinutes; [1247][1248][1249][1250][1251][1252][1253][1254] undefined 43 98.6 totalMinutes temperature days

140 7- 140 Aliasing Two different variables can refer to the same object (we’ve seen this before); this is known as aliasing Time dawn, sunrise; dawn = new Time(5, 35); sunrise = dawn; sunrise Attributes: _hour = 5 _minute = 35 Methods: … dawn

141 7- 141 Time dawn, sunrise; dawn = new Time(5, 35); sunrise = dawn; Aliasing [1247][1248][1249][1250][1251][1252][1253][1254] undefined 43 12 98.6 totalMinutes temperature days dawn Attributes: _hour = 5 _minute = 35 Methods: … heap sunrise 29427

142 7- 142 Time dawn, sunrise; dawn = new Time(5, 35); sunrise = dawn; I Can Draw It This Way [1247][1248][1249][1250][1251][1252][1253][1254] undefined 43 12 98.6 totalMinutes temperature days dawn Attributes: _hour = 5 _minute = 35 Methods: … heap sunrise

143 7- 143 Any operation that changes one alias also affects the other one Let’s say we change the dawn object; then the sunrise object is also affected (since it’s the same object); we'll define "advanceMinutes()" later: dawn.advanceMinutes(70); //change object's attributes sunrise Attributes: _hour = 6 _minute = 45 Methods: … dawn

144 7- 144 Aliasing [1247][1248][1249][1250][1251][1252][1253][1254] undefined 43 12 98.6 totalMinutes temperature days dawn Attributes: _hour = 6 _minute = 45 Methods: … heap sunrise 29427 dawn.advanceMinutes(70);

145 7- 145 Time dawn, sunrise; dawn = new Time(5, 35); sunrise = dawn; dawn.advanceMinutes(70); // change object's attributes sunrise.printTime( ); // prints 6:45AM The Effect sunrise Attributes: _hour = 6 _minute = 45 Methods: … dawn 29427 heap

146 7- 146 The Effect sunrise Attributes: _hour = 6 _minute = 45 Methods: … dawn Time dawn, sunrise; dawn = new Time(5, 35); sunrise = dawn; dawn.advanceMinutes(70); // change object's attributes sunrise.printTime( ); // prints 6:45AM

147 7- 147 What Does This Mean for Parameter Passing? In Java, arguments are copied into formal parameters of a method For simple types (like int and double), this means that the method has only a copy of the original variable For object types, this means that the method has a copy of the reference to, i.e., the address of, the original object (and can mutate the original object)

148 7- 148 Example: Original Definition of addMinutes( ) public Time addMinutes (int m) { int totalMinutes = ((60*_hour)+ _minute + m)%(24*60); if (totalMinutes < 0) totalMinutes = totalMinutes + (24*60); return new Time(totalMinutes/60, totalMinutes%60); } Calculation of totalMinutes is done within the method.

149 7- 149 New Definition of addMinutes( ) Calculation of totalMinutes is done outside of addMinutes( ), inside calculate( ). We want calculate( ) to change the value of totalMinutes. It doesn’t happen. public Time addMinutes (int m) { int totalMinutes; calculate(totalMinutes, m); return new Time(totalMinutes/60, totalMinutes%60); } public void calculate(int total, int i) { total = ((60*_hour) + _minute + i) % (24*60); if (total < 0) total = total + (24*60); }

150 7- 150 Example: What’s Happening on the Stack? Method main( ) STACK args: ? start: start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) heap Method addMinutes( ) Came from: main, line 4 this: m: 30 totalMinutes: ? top

151 7- 151 Now we call calculate( ) Method main( ) STACK args: ? start: start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) heap Method addMinutes( ) Came from: main, line 4 this: m: 30 totalMinutes: ? Method calculate( ) Came from: addMinutes, line 2 this: i: 30 total: ? totalMinutes had no value at the time of the call, so total has no starting value top

152 7- 152 calculate( ) assigns a value to total Method main( ) STACK args: ? start: start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) heap Method addMinutes( ) Came from: main, line 4 this: m: 30 totalMinutes: ? Method calculate( ) Came from: addMinutes, line 2 this: i: 30 total: 540 total now has a value, but totalMinutes still has none top

153 7- 153 calculate( ) returns nothing to addMinutes( ) Method main( ) STACK args: ? start: start Attributes: _hour = 8 _minute = 30 Methods: Time addMinutes(int m) void printTime ( ) heap Method addMinutes( ) Came from: main, line 4 this: m: 30 totalMinutes: ? totalMinutes still has no value; addMinutes( ) will not work correctly top

154 7- 154 Bottom Line, call-by-value: total is just a copy of totalMinutes Since total is just a copy of totalMinutes, changes made to total do not cause changes to totalMinutes public Time addMinutes (int m) { int totalMinutes; calculate(totalMinutes, m); return new Time(totalMinutes/60, totalMinutes%60); } public void calculate(int total, int i) { total = ((60*_hour) + _minute + i) % (24*60); if (total < 0) total = total + (24*60); }

155 7- 155 Something Similar When Objects are Passed as Arguments public Time addHours (Time t, int m) { advanceBy(t, m*60); return t; } public void advanceBy(Time theNewTime, int m) { theNewTime = theNewTime.addMinutes(m); } In advanceBy( ), a new Time object is generated and assigned to theNewTime. This does not affect the value of t in addHours( ).

156 7- 156 One Solution, to Get t Changed public Time addHours (Time t, int m) { t = advanceBy(t, m*60); return t; } public Time advanceBy(Time theNewTime, int m) { theNewTime = theNewTime.addMinutes(m); return theNewTime; }

157 7- 157 First Solution, Shorter public Time addHours (Time t, int m) { return advanceBy(t, m*60); } public Time advanceBy(Time theNewTime, int m) { return theNewTime.addMinutes(m); }

158 7- 158 Second Solution, to Get t Changed public Time addHours (Time t, int m) { advanceBy(t, m*60); return t; } public void advanceBy(Time theNewTime, int m) { theNewTime.advanceMinutes(m); } We'll look at advanceMinutes() again later.

159 7- 159 What it Looks Like, when advanceBy( ) is called heap Method main( ) STACK args: ? start: Method addHours() Came from: main, line 8 this: m: 2 t: Method advanceBy( ) Came from: addHours, line 1 this: m: 120 theNewTime: start Attributes:Methods: _hour = 8... _minute = 30 Attributes:Methods: _hour = 13... _minute = 45 t, theNewTime

160 7- 160 What it Looks Like, after advanceBy( ) calls addMinutes( ) heap Method main( ) STACK args: ? start: Method addHours() Came from: main, line 8 this: m: 2 t: Method advanceBy( ) Came from: addHours, line 1 this: m: 120 theNewTime: start Attributes:Methods: _hour = 8... _minute = 30 Attributes:Methods: _hour = 13... _minute = 45 t, theNewTime Attributes:Methods: _hour = 15... _minute = 45

161 7- 161 What it Looks Like, at the end of advanceBy( ); theNewTime is changed, but not t heap Method main( ) STACK args: ? start: Method addHours() Came from: main, line 8 this: m: 2 t: Method advanceBy( ) Came from: addHours, line 1 this: m: 120 theNewTime: start Attributes:Methods: _hour = 8... _minute = 30 Attributes:Methods: _hour = 13... _minute = 45 t Attributes:Methods: _hour = 15... _minute = 45 theNewTime

162 7- 162 Call-by-value for Object Arguments When we passed the value of t into theNewTime, we were passing a reference to an object, not the object itself At the start of advanceBy( ), both t and theNewTime were pointing at the same object in the heap If advanceBy( ) had actually changed the object, rather than just generating a new one, then t would have been affected, too

163 7- 163 If advanceBy( ) had changed theNewTime’s object, t’s object would have been changed heap Method main( ) STACK args: ? start: Method addHours() Came from: main, line 8 this: m: 2 t: Method advanceBy( ) Came from: addHours, line 1 this: m: 120 theNewTime: start Attributes:Methods: _hour = 8... _minute = 30 Attributes:Methods: _hour = 13... _minute = 45 t, theNewTime

164 7- 164 Variable Scope What happens if you use the same name for an instance variable, a formal parameter, and a local variable? It’s illegal to use the same name for a formal parameter of a method and a local variable in the same method It is all right to use the same name for an instance variable and either a formal parameter or local variable

165 7- 165 Legal Use of Variable x class C { int x;... void f (String y) { double x;... … x... } } instance variable called x; by convention, we would normally write “_x” This x refers to the local variable local variable called x

166 7- 166 Formal Parameter x class C { int x;... void f (double x) {...... … x... } } instance variable called x; by convention, we would normally write “_x” This x refers to the formal parameter formal parameter called x

167 7- 167 Scope of Variables in Java The scope of a variable is the part of a program in which that variable can be referenced The scope of a formal parameter or local variable is the body of its method The scope of an instance variable is its entire class, except where there is a formal parameter or local variable of the same name; that creates a “hole” in its scope

168 7- 168 Hole in the scope of instance variable x class C { int x;... void f (double x) { … } void g (int y) { … } } scope of instance variable x hole in scope

169 7- 169 Using “this” to reference a hidden variable class C { int x; … void f (double x) { … x … … this.x … } void g (int y) { … } } This x refers to the formal parameter This x refers to the instance variable for the class C instance variable called x; by convention, we would normally write “_x”

170 7- 170 Changing Attribute Values: Mutability The Time class, as we’ve defined it so far, never has its attributes changed The constructor of a Time object assigns values to its attributes Nothing can change those attributes (no methods exist to do it, no outside assignment can do it) The Time class is an immutable class or immutable type

171 7- 171 Things Don’t Have to Be This Way Methods are allowed to change instance variables by assignment This is, in fact, a very common and useful thing for objects to be able to do to themselves, in response to a message Such methods are called mutating operations A class that has such methods is called a mutable class or mutable type

172 7- 172 Let’s Make Time a Mutable Class We’ll add the following mutating operation on the Time class (similar to addMinutes, but addMinutes left the Time object unchanged): public void advanceMinutes (int m) { int totalMinutes = ((60*_hour) + _minute + m) % (24*60); if (totalMinutes < 0) totalMinutes = totalMinutes + (24*60); hour = totalMinutes / 60; minute = totalMinutes % 60; } The 2 mutating assignments

173 7- 173 Consider the Following Example Time lunchtime = new Time(12, 0), dinnertime = new Time(0, 0); lunchtime.printTime( );// prints: noon lunchtime.advanceMinutes(10); lunchtime.printTime( );// prints: 12:10PM dinnertime = lunchtime.addMinutes(6 * 60); lunchtime.printTime( ); // still prints: 12:10PM dinnertime.printTime( );// prints: 6:10PM

174 7- 174 Creation of Two New Objects Timelunchtime = new Time(12, 0), dinnertime = new Time(0, 0); lunchtime Attributes: _hour = 12 _minute = 0 Methods: … dinnertime Attributes: _hour = 0 _minute = 0 Methods: …

175 7- 175 lunchtime.advanceMinutes(10); advanceMinutes(10) lunchtime Attributes: _hour = 12 _minute = 0 Methods: …

176 7- 176 The result of the advanceMinutes(10) message lunchtime Attributes: _hour = 12 _minute = 10 Methods: …

177 7- 177 lunchtime.addMinutes(6 * 60) addMinutes(6 * 60) lunchtime Attributes: _hour = 12 _minute = 10 Methods: …

178 7- 178 The result of the addMinutes(6 * 60) message lunchtime Attributes: _hour = 12 _minute = 10 Methods: … Attributes: _hour = 18 _minute = 10 Methods: …

179 7- 179 dinnertime = lunchtime.addMinutes(6 * 60); lunchtime Attributes: _hour = 12 _minute = 10 Methods: … Attributes: _hour = 18 _minute = 10 Methods: … dinnertime garbage

180 7- 180 Methods that return values are expressions; methods that are void are statements It is illegal to write: lunchtime = lunchtime.advanceMinutes(10); Why? It is illegal to write: lunchtime.addMinutes(10); Why? A void method suggests that it is a mutating operation; a method with a return value suggests it is not a mutating operation, but not for sure.

181 7- 181 Mutable vs. Immutable Classes (another way of saying it) For an immutable class C, the value of the object being pointed to by a variable of type C (like “bill”) can be changed only by an assignment statement: bill = … For a mutable class, the value of the object being pointed to by a variable of type C (like “dinnertime” or “lunchtime”) can be changed either by assignment or by sending the right message: dinnertime = lunchtime.addMinutes(6 * 60); lunchtime.advanceMinutes(10);

182 7- 182 public void advanceMinutes (int m) { int totalMinutes = ((60*_hour) + _minute + m) % (24*60); if (totalMinutes<0) totalMinutes=totalMinutes + (24*60); hour = totalMinutes / 60; minute = totalMinutes % 60; } public Time addMinutes (int m) { int totalMinutes = ((60*_hour) +_minute + m)%(24*60); if (totalMinutes < 0) totalMinutes = totalMinutes + (24*60); return new Time(totalMinutes/60, totalMinutes%60); } Review: addMinutes vs. advanceMinutes addMinutes generates new Time object advanceMinutes mutates original Time object

183 7- 183 Review: Passing a Reference to an Object as an Argument public Time addHours (Time t, int m) { advanceBy(t, m*60); return t; } public void advanceBy(Time theNewTime, int m) { theNewTime = theNewTime.addMinutes(m); } In advanceBy( ), a new Time object is generated and assigned to theNewTime. This does not affect the value of t in addHours( ).

184 7- 184 Review: What it Looks Like, at the end of advanceBy( ); theNewTime (object) is changed, but not t (object) heap Method main( ) STACK args: ? start: Method addHours() Came from: main, line 8 this: m: 2 t: Method advanceBy( ) Came from: addHours, line 1 this: m: 120 theNewTime: start Attributes:Methods: _hour = 8... _minute = 30 Attributes:Methods: _hour = 13... _minute = 45 t Attributes:Methods: _hour = 15... _minute = 45 theNewTime

185 7- 185 Now, what if instead we called a mutating method? public Time addHours (Time t, int m) { advanceBy(t, m*60); return t; } public void advanceBy(Time theNewTime, int m) { theNewTime.advanceMinutes(m); } In advanceBy( ), the original object (pointed to by both t and theNewTime) is now changed. This does affect the value of t’s object in addHours( ).

186 7- 186 What it Now Looks Like, at the end of advanceBy( ); theNewTime (object) is changed, and so is t (object) heap Method main( ) STACK args: ? start: Method addHours() Came from: main, line 8 this: m: 2 t: Method advanceBy( ) Came from: addHours, line 1 this: m: 120 theNewTime: start Attributes:Methods: _hour = 8... _minute = 30 Attributes:Methods: _hour = 15... _minute = 45 t, theNewTime

187 7- 187 What it Now Looks Like, at the end of advanceBy( ); theNewTime (object) is changed, and so is t (object) heap Method main( ) STACK args: ? start: 2196 Method addHours() Came from: main, line 8 this: 2196 m: 2 t: 19364 Method advanceBy( ) Came from: addHours, line 1 this: 2196 m: 120 theNewTime: 19364 start Attributes:Methods: _hour = 8... _minute = 30 Attributes:Methods: _hour = 15... _minute = 45 t, theNewTime 2196 19364

188 7- 188 From C to Shining C In Java, even though an object variable is (in fact) a number (i.e., an address), you cannot add to it, subtract from it, or use its value! You can: –Send a message to the object the variable addresses –Assign an object variable’s value to another object variable (so they address the same location), i.e., “dawn = sunrise;”

189 7- 189 Object Oriented Programming Objects in the computer are supposed to correspond to objects in the real world “The basic idea of object-oriented programming is that programs manipulate objects that correspond to objects in the real world”

190 7- 190 Creating a Class In creating classes to mimic the real world system, we need to decide on: –The appropriate objects –Their interfaces, which will be known to the outside users of our objects –The internal representation for the objects (implementing the objects) The representation affects how easy it will be to program the methods and how efficient the methods will be

191 7- 191 Six Examples Checkers Game Chess Game Address Book Date Book Simulation of Football Simulation of Baseball Consider the class definitions and interfaces that would allow a client to create programs.

192 7- 192 Clients and Classes In examples I give, I sometimes just present the client, and sometimes just present the classes it uses. Of course, the client is a class, too, the one with the primary method main( ). The complete system consists of both: client, e.g., Scheduleclass, e.g., Time

193 7- 193 Example: A Tic-Tac-Toe Board Let’s create a class to represent the tic-tac-toe board It’s an important object in the game It needs to have a place to store the X’s and O’s, and should provide methods for placing them, and for asking if a location has an X, an O, or is blank It might also keep track of whose move is next, and whether someone has won

194 7- 194 Different alternatives Let’s consider various alternatives Let’s assume the following numbering scheme: 123456789123456789 The first thing is to decide on the board’s interface — what methods it has and what they do

195 7- 195 One Possibility For a TTTBoard object: boolean isMarked (int square) int getMark (int square) void putO (int square) void putX (int square) getMark returns the mark (if any in a given square); returns 0 for O, 1 for X, 2 otherwise

196 7- 196 What About “Erroneous” Actions? In case the client passes a number outside 1 to 9, the methods do the following: isMarked: returns false getMark: returns 2 putO: do nothing, leave board unchanged putX: do nothing, leave board unchanged With putO and putX, if the client asks to put a mark on an occupied square, the request is ignored and the board is unchanged

197 7- 197 Division of Labor, client and class In general, there is a trade-off between the work that is done by the client and that done by the object itself Sometimes we can make the class do more work, and save the client work, and vice versa It’s a design decision when the system is built

198 7- 198 Now We are Talking about the Class, used by the Client For the tic-tac-toe board, what will the class definition look like? client, e.g., Playerclass, e.g., TTTBoard

199 7- 199 The Structure of the TTTBoard Class Definition class TTTBoard { instance variables; public TTTBoard ( ) { initialize empty board … } public boolean isMarked (int square) {…} public int getMark (int square) {…} public void putO (int square) {…} public void putX (int square) {…} } constructor definition declarations of class attributes 4 method definitions

200 7- 200 Representation Now, let’s decide on a representation for the squares on the board We could use a variable for each square, which contains zero for O, one for X, and 2 if it is empty (This is a common technique, to use an otherwise unused value to mean “empty” or “undefined”)

201 class TTTBoard { private int _sq1, _sq2, _sq3, _sq4, _sq5, _sq6, _sq7, _sq8, _sq9; // Each square contains 2 if empty, // 0 for O, 1 for X public TTTBoard ( ) { _sq1 = 2; _sq2 = 2; _sq3 = 2; _sq4 = 2; _sq5 = 2; _sq6 = 2; _sq7 = 2; _sq8 = 2; _sq9 = 2; } public boolean isMarked (int square) {...} public int getMark (int square) {...} public void putO (int square) {...} public void putX (int square) {...} }

202 7- 202 One of the Methods (the rest are similar) public boolean isMarked (int square) { switch (square) { case 1: return (_sq1 != 2); case 2: return (_sq2 != 2); case 3: return (_sq3 != 2); case 4: return (_sq4 != 2); case 5: return (_sq5 != 2); case 6: return (_sq6 != 2); case 7: return (_sq7 != 2); case 8: return (_sq8 != 2); case 9: return (_sq9 != 2); default: return false; } Why no break statements?

203 7- 203 Changing the Implementation of a Class Encapsulation allows us to change an implementation of a class without affecting other parts of the program. Without encapsulation changes to implementation might “break” the program – many changes Why would we want to change the implementation? –Different implementations have different tradeoffs (e.g., space conservation, efficiency etc.)

204 7- 204 We Could Use a Completely Different Internal Representation Let’s say we wanted the methods of TTTBoard to be shorter Let’s change the representation of the board, so that instead of using 9 separate instance variables, we’ll use a single integer to represent the whole board The largest possible integer in Java is 2,147,483,647

205 7- 205 A Single int for the Whole Board Ones digit is square 1, tens digit is square 2, hundreds digit is square 3, etc. 123456789123456789 9’s, 8’s, 7’s, 6’s, 5’s, 4’s, 3’s, 2’s, 1’s

206 7- 206 A Single int for the Whole Board So here is one example, with (as usual) 0 for O, 1 for X, and 2 for empty XXOOXXXOOX 120,220,211 position 1position 9 let’s call this private int variable “_boardSquares”

207 7- 207 Simple Formula Given this representation, the contents of square s in board B is (B/10 s - 1 ) mod 10 The division throws away the s - 1 digits to the right of the s position, then the mod 10 throws away the remaining digits to the left of the s position

208 7- 208 New isMarked( ) Method public boolean isMarked (int square) { if (square < 1 || 9 < square) return false; else return ((_boardSquares / (int) Math.pow(10, square-1))%10) != 2; } Math.pow computes x y for doubles x and y.

209 7- 209 New TTTBoard2 Constructor and New getMark( ) public TTTBoard2 ( ) { _boardSquares = 222222222; } public int getMark (int square) { if (square < 1 || 9 < square) return 2; else return (_boardSquares / (int) Math.pow(10,square-1)) % 10; }

210 7- 210 Some Things Get Trickier To place a mark in a square: –The square must be unoccupied ( i.e., contain a 2 ) –Then the 2 must be removed and replaced with a 0 or a 1 B - (2 * 10 s-1 ),to place an O B - (2 * 10 s-1 ) + 10 s-1,to place an X { change B to But the interfaces of putO and putX are still unchanged

211 7- 211 New putO( ) public void putO (int square) { if (square < 1 || 9 < square) return; if (isMarked(square)) return; _boardSquares = _boardSquares - (int) (2 * Math.pow(10, square-1)); }

212 7- 212 New putX( ) public void putX (int square) { if (square < 1 || 9 < square) return; if (isMarked(square)) return; _boardSquares = _boardSquares - (int) (Math.pow(10, square-1)); }

213 7- 213 Representation Independence Notice that changing the representation in these cases did not change the interface This is called “representation independence”, and is an important feature in using Java classes Using the private keyword is an important part of this feature

214 7- 214 What if the Client Wrote the Following? TTTBoard board1 = new TTTBoard( ); if (board1._sq1 == 2) System.out.println(“Square 1 is unoccupied”); The client gets an error message: “No variable _sq1 defined in class TTTBoard” This happens because our instance variables (in both representations) are declared as private If they had been declared public, then this would have worked with the first representation, and not worked with the second representation Terrible! Unacceptable! Bad for large programs!

215 7- 215 Interface and Representation Sometimes, changing the interface can force a change in the representation (e.g., having the board enforce alternating moves) See the Mickunas book for more examples None of these representations is very good (e.g., they are not extensible to larger boards, more dimensions)

216 7- 216 An Interface Change that Requires a Change in Representation class TTTBoard3 { private int _boardSquares; private boolean _xMovesNext; public TTTBoard3 ( ) { _boardSquares = 222222222; _xMovesNext = true; } public boolean isMarked (int square) {…} public int getMark (int square) {…} public void putO (int square) {…} public void putX (int square) {…} }

217 7- 217 Another new putO( ) public void putO (int square) { if (_xMovesNext) { System.out.println ( “Attempted move out of turn” ); return; } if (square < 1 || 9 < square) return; if (isMarked(square)) return; _boardSquares = _boardSquares - (int) (2 * Math.pow(10, square-1)); _xMovesNext = true; }

218 7- 218 Another new putX( ) public void putX (int square) { if (!_xMovesNext) { System.out.println( “Attempted move out of turn” ); return; } if (square < 1 || 9 < square) return; if (isMarked(square)) return; _boardSquares = _boardSquares - (int) (Math.pow(10, square-1)); _xMovesNext = false; }


Download ppt "Introduction to Computer Science Classes and Methods I »Objects »Instance Methods »Formal Parameters, the Stack, Call-by-Value, Scope of Variables, Mutable."

Similar presentations


Ads by Google