










Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Community
Ask the community for help and clear up your study doubts
Discover the best universities in your country according to Docsity users
Free resources
Download our free guides on studying techniques, anxiety management strategies, and thesis advice from Docsity tutors
Material Type: Assignment; Class: LAB:Comp Program & Prob Solv; Subject: Computer Science; University: Wellesley College; Term: Fall 2007;
Typology: Assignments
1 / 18
This page cannot be seen from the preview
Don't miss anything!
As a first example, we consider the StitchWorld and Stitcher classes on the next page in Fig. 3. The StitchWorld class is a subclass of BuggleWorld that overrides the run method of BuggleWorld. This run method creates two instances of the Stitcher class, which extends the Buggle class with five new methods: stitch4, stitch2, stitch, box, and turn180. All these methods are void methods (i.e., they return no results) that take no parameters. We can understand what the StitchWorld run method does by carefully drawing a Java Ex- ecution Model (JEM) diagram (see Fig. 1) for an invocation of the run method. Such a diagram
Figure 1: Initial JEM diagram for the StitchWorld example. Execution Land → SW .run();
Object Land StitchWorld SW
shows execution frames in Execution Land and objects in Object Land. We assume that run is invoked on an instance of StitchWorld with object label SW. The StitchWorld instance SW is a complex object whose state we do not wish to study in detail, so we shall treat it (and draw it) as a “black box”. The control arrow, → , indicates which statement is currently being executed. Invoking the run method on SW creates an execution frame (Fig. 2). As always, the this
Figure 2: Invoking run() creates an execution frame. Execution Land
SW .run();
this SW → Stitcher sue = new Stitcher(); sue.setPosition(new Location(4,2)); Stitcher sam = new Stitcher(); sam.setColor(Color.blue); sue.stitch4(); sam.box();
Object Land StitchWorld SW
variable of the execution frame is the receiver object — the object on which the method was invoked — in this case, SW.
public class StitchWorld extends BuggleWorld {
public void run () { Stitcher sue = new Stitcher(); sue.setPosition(new Location(4,2)); Stitcher sam = new Stitcher(); sam.setColor(Color.blue); sue.stitch4(); sam.box(); }
}
public class Stitcher extends Buggle {
public void stitch4 () { this.stitch2(); this.stitch2(); }
public void stitch2 () { this.stitch(); this.stitch(); }
public void stitch () { this.forward(); this.left(); this.forward(); this.right(); }
public void box () { this.stitch(); // draw two sides of box this.turn180(); // turn to draw rest of box this.stitch(); // draw other two sides of this.turn180(); // turn to original heading this.stitch(); // move to opposite corner }
public void turn180 () { this.left(); this.left(); } }
Figure 3: Code for the StitchWorld example.
The result of these three steps is depicted in Fig. 5.
Figure 5: JEM after executing the second statement in the run method. Execution Land
SW .run();
this SW sue S Stitcher sue = S1 ; S1 .setPosition( (4,2) ); → Stitcher sam = new Stitcher(); sam.setColor(Color.blue); sue.stitch4(); sam.box();
Object Land
StitchWorld SW
Stitcher S
position (4,2)
heading EAST
color red
brushDown? true
Control now points to the third statement of the run method: Stitcher sam = new Stitcher();
Executing this assignment statement (1) creates a new local variable named sam; (2) creates an- otherStitcher instance, which we shall assume has object label S2 ; and (3) stores S2 the local variable named sam. The result of these steps is shown in Fig. 6. Now control points to the fourth statement of the run method: sam.setColor(Color.blue);
Executing this void method invocation statement (1) evaluates the receiver expression sam to S2 ;
(2) evaluates the argument expression Color.blue to the object reference blue for an pre-existing
Color instance in Object Land; and (3) changes the color of S2 to blue. The result of these steps is shown in Fig. 7. Next comes the execution of the fifth statement in the run method, s1.stitch4();. This is an invocation of a user-defined method, stitch4, on the receiver expression s1, whose value is S.
Such an invocation creates a new execution frame whose this variable contains the receiver, S (Fig. 8). Since Object Land remains unchanged from Fig. 7), we do not show it.
Figure 6: JEM after executing the third statement of the run method. Execution Land
SW .run();
this SW sue S1 sam S Stitcher sue = S1 ; S1 .setPosition( (4,2) ); Stitcher sam = S2 ; → sam.setColor(Color.blue); sue.stitch4(); sam.box();
Object Land
StitchWorld SW
Stitcher S
position (4,2)
heading EAST
color red
brushDown? true
Stitcher S
position (1,1)
heading EAST
color red
brushDown? true
Figure 7: JEM after executing the fourth statement of the run method. Execution Land
SW .run();
this SW sue S1 sam S Stitcher sue = S1 ; S1 .setPosition( (4,2) ); Stitcher sam = S2 ; S2 .setColor( blue ); → sue.stitch4(); sam.box();
Object Land
StitchWorld SW
Stitcher S
position (4,2)
heading EAST
color red
brushDown? true
Stitcher S
position (1,1)
heading EAST
color blue
brushDown? true
Figure 11: JEM after completing the first invocation of stitch.
Execution Land this SW sue S1 sam S Stitcher sue = S1 ; S1 .setPosition( (4,2) ); Stitcher sam = S2 ; S2 .setColor( blue ); S1 .stitch4(); sam.box();
this S S1 .stitch2(); this.stitch2();
this S S1 .stitch(); → this.stitch();
this S S1 .forward(); S1 .left(); S1 .forward(); S1 .right();
Object Land
StitchWorld SW
Stitcher S
position (5,3)
heading EAST
color red brushDown? true
Stitcher S
position (1,1)
heading EAST
color blue brushDown? true
After executing all four statements in the execution frame for the first stitch invocation within stitch2, the execution of that invocation is complete, and the control arrow proceeds to execute the second invocation of stitch within stitch2. In reality, the execution frame for the first stitch invocation disappears at this point, but we will continue to display it to show the history of the computation. Executing the second invocation of stitch within stitch2 creates a second execution frame for stitch (Fig. 12). Performing the four statements in the second stitch execution frame yields
Figure 12: The second invocation of stitch in stitch2 creates a second execution frame for stitch.
Execution Land
this SW sue S1 sam S Stitcher sue = S1 ; S1 .setPosition( (4,2) ); Stitcher sam = S2 ; S2 .setColor( blue ); S1 .stitch4(); sam.box();
this S S1 .stitch2(); this.stitch2();
this S S1 .stitch(); S1 .stitch();
this S S1 .forward(); S1 .left(); S1 .forward(); S1 .right();
this S → this.forward(); this.left(); this.forward(); this.right();
the JEM diagram in (Fig. 13).
Figure 13: JEM after completing the second invocation of stitch. Execution Land
this SW sue S1 sam S Stitcher sue = S1 ; S1 .setPosition( (4,2) ); Stitcher sam = S2 ; S2 .setColor( blue ); S1 .stitch4(); sam.box();
this S S1 .stitch2(); → this.stitch2();
this S S1 .stitch(); S1 .stitch();
this S S1 .forward(); S1 .left(); S1 .forward(); S1 .right();
this S S1 .forward(); S1 .left(); S1 .forward(); S1 .right();
Object Land
StitchWorld SW
Stitcher S
position (6,4)
heading EAST
color red brushDown? true
Stitcher S
position (1,1)
heading EAST
color blue brushDown? true
Since the first invocation of stitch2 is now complete, control proceeds to the second invocation of stitch2. Just as in the first invocation of stitch2, the second invocation will cause the creation of three new execution frames in the JEM. We shall not show the intermediate steps, just the final state after the execution of the second invocation of stitch2 (Fig. 14). The execution of sam.box creates six new execution frames, which are shown in Fig. 15 in the final picture of Execution Land for the StichWorld example. The final state of Object Land for this example is shown in Fig. 16. Even though the StitchWorld methods are very simple (they take no parameters and return no results), they illustrate some important aspects of JEM diagrams and of programming in general:
Figure 15: Final state of Execution Land in the StitchWorld example.
Execution Land
this SW sue S1 sam S
Stitcher sue = S1 ; S1 .setPosition( (4,2) ); Stitcher sam = S2 ; S2 .setColor( blue ); S1 .stitch4(); S2 .box();
this S S1 .stitch2(); S1 .stitch2();
this S S1 .stitch(); S1 .stitch();
this S S1 .forward(); S1 .left(); S1 .forward(); S1 .right();
this S S1 .forward(); S1 .left(); S1 .forward(); S1 .right();
this S S1 .stitch(); S1 .stitch();
this S S1 .forward(); S1 .left(); S1 .forward(); S1 .right();
this S S1 .forward(); S1 .left(); S1 .forward(); S1 .right();
this S S2 .stitch(); S2 .turn180(); S2 .stitch(); S2 .turn180(); S2 .stitch();
this S S2 .forward(); S2 .left(); S2 .forward(); S2 .right(); this S S2 .left(); S2 .left(); this S S2 .forward(); S2 .left(); S2 .forward(); S2 .right(); this S S2 .left(); S2 .left();
this S S2 .forward(); S2 .left(); S2 .forward(); S2 .right();
Figure 16: Final state of Object Land in the StitchWorld example. Object Land
StitchWorld SW
Stitcher S
position (8,6)
heading EAST
color red
brushDown? true
Stitcher S
position (2,2)
heading EAST
color blue
brushDown? true
sequence of statements in the leaf frames, we can instead write a few method invocations that “expand” into those statements. For instance, in the above example, each of stitch4() and box() expands into 16 primitive statements in the leaf frames. In this way, collections of methods give the programmer a way to “amplify” the power of a statement; a single statement can denote a complex sequence of actions.
assume has object label LB1 , and stores this in a new local variable named liam (Fig. 20).
Figure 20: A LineBuggle named liam is born. Execution Land
LBW .run();
this LBW LineBuggle liam = LB1 ; → liam.corner(Color.blue, Color.green, 4);
Object Land
StitchWorld LBW
LineBuggle LB
position (1,1)
heading EAST
color red
brushDown? true
The second statement in the body of run is an instance method invocation. Before the method can be invoked, it is necessary to (1) evaluate the receiver expression (in this case, the variable reference liam) and (2) evaluate all the argument expressions (in this case, the class constants Color.blue and Color.green and the integer literal 4 ). These evaluations yield the statement:
LB1 .corner( blue , green , 4)
Once the receiver and argument expressions have been evaluated, the execution frame for the invocation of corner can be created. In addition to the this variable, which always contains the value of the receiver expression, the frame contains one variable for each formal parameter in the method declaration (in this case, c1, c2, and n). These variables are filled with the respective values of the argument expressions, as shown in Fig. 21.
Figure 21: Creation of the execution frame for the corner invocation. Execution Land
LBW .run();
this LBW liam LB LineBuggle liam = LB1 ; LB1 .corner( blue , green , 4);
this LB1 c1 blue
c2 green n 4 → this.line(c1, n+1); this.left(); this.line(c2, n-1);
The first statement in the body of corner is an invocation of the line instance method. First, we need to evaluate the receiver expression, this, whose value is LB1. Next, we evaluate the
argument expressions c1 (whose value is blue ) and n+1 (whose value is 5). Finally, we perform
the invocation LB1 .line( blue ,5) by creating a new execution frame (Fig. 22). In addition to the this variable, the new frame has one variable for each of the formal parameters, col and len:
Figure 22: Creation of the execution frame for the first line invocation. Execution Land
LBW .run();
this LBW liam LB LineBuggle liam = LB1 ; LB1 .corner( blue , green , 4);
this LB1 c1 blue
c2 green n 4 LB1 .line( blue , 5); this.left(); this.line(c2, n-1);
this LB
col blue
len 5 → this.setColor(col); this.forward(len);
Executing the two statements in the body of the line method changes Execution Land and Object Land as shown in Fig. 23.
Figure 23: Creation of the execution frame for the first line invocation. Execution Land
LBW .run();
this LBW liam LB LineBuggle liam = LB1 ; LB1 .corner( blue , green , 4);
this LB1 c1 blue
c2 green n 4 LB1 .line( blue , 5); → this.left(); this.line(c2, n-1);
this LB
col blue
len 5 LB1 .setColor( blue ); LB1 .forward(5);
Object Land
StitchWorld LBW
LineBuggle LB
position (6,1)
heading EAST
color blue
brushDown? true
Next the left method invocation in corner is executed, yielding the JEM in Fig. 24. Finally, the third statement of the corner method, this.line(c2, n-1), is executed. To execute this instance method invocation, it is first necessary to evaluate the receiver expression (the variable reference this) and the argument expressions (the variable reference c2 and the binary application n-1). The values of these expressions are LB1 , green , and 3 , respectively. The invocation LB1 .line( green ,3) is performed by creating a new execution frame (Fig. 25). Executing the two statements in the body of the second line frame gives the final Execution Land and Object Land for this example (Fig. 26). The LineBuggleWorld example illustrates the key important fact about methods with parame- ters: the variables named by the parameters enable the same method body to do different things for different method invocations. Consider the line method in the above example. The two invocations
Figure 26: The final JEM diagram for the LineBuggleWorld example. Execution Land
LBW .run();
this LBW liam LB LineBuggle liam = LB1 ; LB1 .corner( blue , green , 4);
this LB1 c1 blue
c2 green n 4 LB1 .line( blue , 5); LB1 .left(); LB1 .line( green , 3);
this LB
col blue
len 5 LB1 .setColor( blue ); LB1 .forward(5);
this LB
col green
len 3 LB1 .setColor( green ); LB1 .forward(3);
Object Land
StitchWorld LBW
LineBuggle LB
position (6,4)
heading NORTH
color green
brushDown? true
execute exactly the same two statements: this.setColor(col); this.forward(len); Yet, the two invocations have different behaviors. Why? The only difference is values stored in the variables named by the parameters. In the first invocation, col denotes blue and len denotes 5 , while in the second invocation col denotes green and len denotes 3. Effectively, the method body acts as a template with “holes” that can be filled in differently for different invocations; the parameters serve as these holes. Here are a few notes concerning the above example:
Although people sometimes get confused by the presence of more than one variable with the same name, Java does not, because it follows a simple rule: when executing the statements in an execution frame, all variable names must refer to the variables at the top of that frame. For instance, each of the line frames can refer to its own this, col, and len variables, but neither can refer to the this, col, and len variables in the other frame, nor can either refer to the this, c1, c2, and n variables in the corner frame. In terms of information flow, this means that if you want a method to use an existing object, you must pass it in as a parameter.^1
(^1) This isn’t technically true, since all methods can refer to the same class constants. And we will learn later how objects can be shared through instance variables. But the intuition that objects are shared by passing them as parameters is a good one.