This collapsed bridge which your instructor is climbing in, located in the backcountry of Cascades National Park in Washington state, is evidence of the profound value of structures: steel and triangles are a nearly unbeatable pair. In Java, member variables and methods are the killer duo.
techred home > mod 2.3: scope and member variables

Module 3: Scope & Member Variables

Parent Content Chunk: 2 - Language Structures

A fully-baked Java class consists of class-wide data elements called member variables, and methods which operate on those member variables. We've been working with methods and variables since day one in this course. Unlike previous modules where we only declared variables inside methods, this module introduces the concept of variable scope which is a set of rules, enforced by the compiler, for controlling which blocks of code can access variables that are declared inside and outside of methods.

preparation

This is the third module in Java Chunk 2: Language Structures. You should work through the following two modules which precede this one before commencing your study:

settingsChunk 2, Module 1: Simple methods

settingsChunk 2, Module 2: Fully-baked methods

contents

Core Concept: Exploring variable scope
Exercise 1: Tracking riders at Kennywood Park
Exercise 1: Extension ideas
Mini Project: Creating a purchase calculator
Module project extension Exercises

lesson objectives

check_box

Describe in English the parts that make up well-formed Java classes and how they work together: Member variables and methods

check_box

Create member variables of appropriate types and justify their placement in class scope rather than method scope

check_box

Create a set of well-designed methods that each accomplish one task and operate on member variables of their hosting class

time considerations

This is a hefty module and digesting its contents should probably be done over two sittings. Set aside 2-3 hours to work through the core concepts and exercises. Then dedicate 3-4 hours to programming your module project and preparing it for sharing.

resources

Course Textbook - Java: Beginner's Guide. Chapter 4 starts with an introduction on Class structure and proceeds into methods, which we learned about prior to this lesson.

Oracle Online tutorial on class structure. Note that this section is part of a larger section on object-oriented programming, which we haven't covered. Unless you want to study ahead, the sections before and after this one on classes would be extra reading.

setup your workspace

Create a new package aclled weekB1_scope and create the following empty class files for use throughout this tutorial:

  • ScopeBasics
  • KennywoodRideTracker
  • OrderTabulator (or your own name)

"submitting"

  1. Code up your mini-project, test it, and comment your code. Please make a note of any outside resources you used for any part of your code by including a link or attribution in your comments.
  2. Upload your file to your personal GitHub account.
  3. Make an entry in our java submission index listing your project under Chunk 2, Module 3 and, as usual, include a link to your file on GitHub.

Module Core Concepts: Exploring variable scope

Scope Essentials

Let's jump right in and get our code dirty with scope! You should have already created a package called weekB1_scope and it contains a class called ScopeBasics. Transfer the following code into this class, reading as you go, line by line. TIP: Write the comments, too--for your brain!

Notice that the code included below contains two errors flagged by the pre-compiler: this is intentional. Make sure your code also has these errors as well and study the error messages carefully. We'll dissect them later in this section.

Listing 1: ScopeBasics which demonstrates basic scope concepts
Class member variables have class scope and can be accesed by any method in the class.

Green means class scope!

If you studied your test class carefully, you probably noticed that our member variable declared in class scope called classScopedVar is automatically colored green. Not surprisingly, this is the way the pre-compiler indicates the variable is in class scope. Variables in white text are local only to the method or block in which it was declared.

Why is out also green?

Now we can understand something about the somewhat mysterious code: System.out.println();. Since out is green, we know that it is actually a member variable located on the System object. The dot operator (what we call the access operator) allows us to access both member variables and methods on objects. In this case, we're accessing a member variable on the System object.

Try compiling this class

When you run this class (you may have to tell NetBeans to go ahead and try running a program with errors), you should see this output which demosntrates that as soon as the JVM reaches a call to access localScope2, an error is encountered. Handily, the error message provides us a line number containing the error: 56.

Figure 1: Output of ScopeBasics class which does not correctly compile because of an attempt to access a variable that is outside the scope in which it was declared.
Class member variables have class scope and can be accesed by any method in the class.

When we go back to line 56 and hover our mouse over the variable localScope2, we see the following message: cannot find symbol even though we have declared this variable on line 34! This makes sense because the variable localScope2 is only accessible inside the block in which it was declared (and any nested blocks, of which there are none in this case). To the pre-compiler, localScope2 only exists inside the demonstrateScope method. It is invisible to all other code in the class.

Class member variables have class scope and can be accesed by any method in the class.

But I want working code!

Since the compiler throws an error with our calls to variables outside of scope, we can fix the errors simply by commenting out the two offending lines, like this:

Commenting out lines that are flagged by the pre-compiler

A close look at the ScopeBasics class

Unlike our run-of-the-mill local variables that are declared inside a method, member variables such as classScopedVar in Listing 1 are declared outside any method and thus are located in "shared" class space. This is handy because any method can read or write this variable which allows us to easily create multiple methods that manipulate the same data.

Study the following diagram of the ScopeBasics class with annotations that discuss the concepts of scope we're exploring so far.

Class member variables have class scope and can be accesed by any method in the class.

When we plan a class, we should declare member variables for values that relate to what the whole class does, such as convert various quantities. If a value is only needed to do a task that a single method carries out, palce the variable in that local method scope.

arrow_upward


Exercise 1: Creating a well-formed Kennywood Ride Tracker Class

Exercise type: In-class code-a-long with Eric

Our goal is to create a class that models folks riding thrill and theme rides at Kennywood. We want the class to contain member variables that track the total number of riders across all rides, so park planners can make staffing and resource decisions. The output can look like this: notice that the Rider Stats track three metrics, each one corresponding to a member variable.

Sample program output for kennywood class.
  1. STUDY steps 2-5 with a partner and a single sheet of paper. NO CODE YET! Create a class diagram like the ones in the images above of the member variables, their names, and the methods, and their calls, in your diagram. We'll use this to code but we want to THINK and PLAN first.
  2. Create a new package called ls3_classStructure. Inside the package, create a class called KennywoodRideTracker. Create a main(String[] arts) method.
  3. Create our member variables that store information that all the methods in the class need to have access to:
    • An integer called totalRiders that is private and static, initalized to zero. This member tracks the total riders that have ridden on any ride in the class.
    • an integer called totalFailedRideAttempts which is private and static and initialized to zero. This will track the number of riders who tried to board a ride but were too short to pass.
    • an integer called totalSickRiders which is private and static and initialized to zero. This will track the number of riders who get sick on the ride. We'll use a random number generator to pick riders to cast a sick spell on.
    • Two final class members to store the minimum height for riders on the thrill rides and the theme rides. You can name these! These should be declared final static and int. Their names should be in all capitals to signal they are constants. Assign a value in inches to each constant; make the thrill ride minimum higher than the theme ride minimum.
  4. Create two ride simulation methods. The first should be named rideBlackWidow. The second method should be called rideMerryGoRound. Both should accept two parameters:
    • An integer called riders
    • An integer called avgHeight
    Both methods should have a return-type of void and be delcared public and static
  5. Create a fourth method (main() plus the two rides) called printRideStats() that accepts no parameters and doesn't reutrn any value. We'll use this method to keep our main() method clear for testing the individual methods. We want to be able to call printRideStats() and see all our member variables' values displayed! This is separation of concerns: this method prints stats. main() tests methods.

    Note that this solution only contains the method signatures but NOT the five member variables. This is an error.


  6. Program the logic inside our ride-simulator methods. We want to pass into each ride a number of riders and their average height. (We'll imagine that all the riders get judged on their average height only.) That sounds like a condition for riding, that can become an if()-controlled block. We want to add our riders and turned away riders to their respective member variables. We also want to generate a random number of riders who get sick and add that to our third member variable.

    Use this method flow diagram to try programming the guts of rideBlackWidow:
    The flow of execution system diagram for a java method's guts Your call to Random.nextInt(int bound) will involve three lines of code: the imprt statment for java.util.Random, a line that creates a Random object, and a line that calls a method on that Random object:

    You can do the import statement-- add the line import java.util.Random right before you declare your class.

    The Random object creation and call to its method are shown here:

    The flow of execution system diagram for a java method's guts
  7. Copy and adapt your rideBlackWidow() method's guts you just wrote into the abodmen of the rideMerryGoRound() method. You should now have two methods ready to accept riders!

  8. Write the code for the printRiderStats(). This is a simple method with only System.out.println() calls which each display one of our three member variables. The output of this method should look something like this: Solution code for this exercise in Java

  9. We're ready to test our methods and member variables in main()! Our code in main() is very simple. We alternate calling printRiderStats() to show the status of our member variables and calling individual ride's methods, passing in a rider count and height of your choosing. Flesh out your main() method with at least 5 calls to rides with riders of various heights, some of which do not pass the minimum threshold. Test your code to make sure the member variables are correctly incremented.

  10. Grab your class diagram and check to see if the diagram and your new code are consistent. Discuss with your partner what the differences are between your plan and how we carried the plan out. Reflect on how you can create more accurate class digrams, please.

access the exercise source

arrow_upward


Extension Ideas

With your initial Kennywood Ride Tracker class up and going, consider the following embellishments to make your program more comprehensive.

You are not asked to upload and share this particular exercise with the course, but if you do some cool renovations to the code provided, by all means please upload your class file and log it in the index for other students to explore!

Idea 1: Percentage statistics

Add code to your class to provide percentage statistics along with the counts of the three tracked rider categories: total rides, failed rides, and sick riders. Compute the percentage of park guests who tried to ride either ride but were turned away due to height restrictions. Also compute the percentage of riders who got sick on each ride. You can display these stats along with the counts in the printRiderStats method.

Idea 2: Randomly generating rider counts

We used a random number generator to simulate some of the riders on each ride getting sick. Expand the use of random number generators to create the initial rider counts and the rider heights. These are currently hard coded in your method calls inside main. You'll want to be thoughtful about how you generate your height values. You can start by just randomly generating a number between some minimum number of inches and a max, but remember heights are not evenly spaced out from 0 inches to X inches. Do some research to see how you can generate a random number between, say 30 inches and 80 inches.

Idea 3: Use looping to simulate many rides

Once you have a random number generating rider counts and heights, create a while() or for() loop system to simulate a specified number of rides. This is the foundations for creating what could become a very advanced park ride simulation tool! Say, for example, we wanted to predict ride usage and optimal park hours. We could integrate such parameters into the program and create special methods that could generate estimated ride counts based on the time of year, the day of the week, the average temperature, etc.! Very cool.

Idea 4: Track sick counts by ride

Split the totalSickRiders member variable into a sick rider count for each of your rides. If you tackled the first extension idea, you can now add a percentage of sick riders by each ride in the park when you display total rider stats. In theory, then, we could track which ride makes folks sicker: the spinning one or the big, scary swinging Black Widow ride. To make this more interesting.

Idea 5: Integrate revenue and profit metrics

Add a ticket price for youth and adults in our KennywoodRideTRacker class. This means two more member variables. Add a third new member variable called totalRevenue that tracks ticket sales overall. Now, if somebody rides a theme ride, like the Merry-go-round, we want to increment the number of "youth" and calculate a total ticket revenue. If a rider rides the thrill ride, consider those riders adults, a multiply the number of riders times the ticket price for adults, and add that value to your totalRevenue member variable. Do the same for youth. Print out the revenue in printRiderStats() method. If you are the finance type, you could also generate a profit metric by creating a hard-coded "cost per rider" amount that attempts to factor in the various costs associated with running an amusement park.

arrow_upward


Module Mini-project: Creating an order tabulator

This project involves creating a system much like the KennywoodRideTracker class which uses member variables to track several quantities which are adjusted by calls to a set of methods which act on that data. Review the project specification carefully and design your class carefully.

program objective

Create a program that could become the basis for a Point-of-sale (POS) system used by staff at a restaurant. The application should manage the ordering of two different food items by tallying the total number of each item which is ordered.

program requirement 1

Create a member variable for each of the two items that the system manages orders for. For example: if the system tracks the number of pizza sliders ordered by all customers, the member variable could be called numPizzaSlidersOrdered. This variable needs to be accessible to all methods.

program requirement 2

Placing an order is simulated by a call to a method dedicated to ordering that particular item. For example: if the user orders three pizza sliders, a method called something like orderPizzaSliders should be called from main and the number of sliders ordered should be passed as an argument to this method.

program requirement 3

Just like the KennywoodRideTracker, create a method called something like displayOrderTotals which can be called by main and lists to the console the running totoal of how many of each item has been ordered so far in the program's execution

program requirement 4

After your core methods are written, flesh out your main method's guts by making a few calls to each of your order methods. You may hard-code the order quantities into the calls to these methods for the purposes of testing in this exercise. If you are feeling confident, build in a user interface such that the user is prompted for the number of each item to purchase and the appropriate methods are called based on that user input.

Sample program output

Output of a program that meets the above specification is included below for your reference. Remember, your program does NOT need to produce output that is EXACTLY like this sample: you are invited to be creative and customize your program.

Solution code for this exercise in Java

Submission

As usual, prepare your class for sharing by commenting all your code, noting any outside resources used in your comments, and checking that the output is clear and neat.

When you are ready, upload the file to your GitHub account and make a corresponding entry in our submission index.

arrow_upward


Mini-project extension activities

Try these adjustments and/or embellishments of your module mini-project.

Extension Idea 1: Add a user interface

Build out your main class by adding user input into the system, as would be the case for any actual point-of-sale system. Allow the user to select which menu items have been ordered and the quantity of each order. You could assume the user is a staff at the restaurant or the end customer. Depending on who your user is will dictate what options the program provides.

Extension Idea 2: Inventory tracking

A common tool that is useful for restaurant owners is a raw material inventory tracker. Design a system for your program to track the amount of raw food goods that are available and provides a running view of how that food stock is depleted as ordered are made. For example, both of the example food items in the output are sliders, which are mini-sandwiches. If your restaurant also served sandwiches, you could create a member variable that represents the total buns in inventory. Each time either slider is ordered, the bun count is depleted by one, etc. You could track meat by ounce and associate each item with a fixed amount of meat per sandwich.

Extension Idea 3: Inventory tracking with outage warnings

Building on extension idea 2, create code that will tell the user if there is not enough raw material in inventory to complete an order. You can make your program useful by telling the user how many items could be ordered if he/she/they request an order that is too large to be filled given current inventory levels. This could potentially get tricky if you are tracking some inventory items that are common among several orderable items: you'll need to decide how to report available orders that can be filled by item.

Extension Idea 4: Order price facilities

Associate each item with an item price and compute an order subtotal, and a final total with tax, for each order submitted. Tally the total order revenue generated during a single program run and display that at the conclusion of the program.

arrow_upward