Part III
Object-Based
Programming
11_597043 pt03.qxd 9/20/05 1:51 PM Page 99
In this part . . .
I
t’s one thing to declare a variable here or there and
to add them and subtract them. It’s quite another
thing to write real programs that people can use —
simple people, but people nonetheless. In this part, you
discover how to group data and how to operate on that
data. You begin to think about programs as collections of
collaborating objects and start designing your own custom
objects. These skills form the basis of all programming
jobs you’ll find in the classifieds.
11_597043 pt03.qxd 9/20/05 1:51 PM Page 100
Chapter 6
Collecting Data — The Class
and the Array
In This Chapter
ᮣ
Introducing the C# class
ᮣ
Storing data in an object
ᮣ
Assigning and using object references
ᮣ
Creating and building arrays of objects
Y
ou can freely declare and use all the intrinsic data types — such as
int
,
double
, and
bool
— to store the information necessary to make your
program the best that it can be. For some programs, these simple variables
are enough. However, most programs need a means to bundle related data in
a neat package.
Some programs need to bundle pieces of data that logically belong together
but aren’t of the same type. For example, a college enrollment application
handles students, each with his or her own name, rank (grade point average),
and serial number. Logically, the student’s name may be a
string
, the grade
point average could be a
double
, and the serial number a
long
. That type of
program needs some way to bundle these three different types of variables
into a single structure called
Student
. Fortunately, C# provides a structure
known as the class for accommodating groupings of unlike-typed variables.
In other cases, programs need to collect a series of like-typed objects. Take,
for example, a program designed to average grades. A
double
does a good
job of representing an individual grade. However, you need some type of col-
lection of
double
variables to contain all the many grades that students
collect during their careers. C# provides the array for just this purpose.
Finally, a real program to process student records would need to graduate
groups of students before they can set out on a life of riches and fame. This
type of program needs both the class and the array concept rolled into one:
arrays of students. Through the magic of C# programming, you can do this
as well.
12_597043 ch06.qxd 9/20/05 1:53 PM Page 101
Showing Some Class
A class is a bundling of unlike data and functions that logically belong together
into one tidy package. C# gives you the freedom to foul up your classes any
way you want, but good classes are designed to represent concepts.
Analysts say that “a class maps concepts from the problem into the pro-
gram.” For example, suppose your problem is to build a traffic simulator. This
traffic simulator is to model traffic patterns for the purpose of building
streets, intersections, and highways. (I would really like you to build a traffic
simulator that could fix the intersection in front of my house.)
Any description of a problem concerning traffic would include the term vehicle
in its solution. Vehicles have a top speed that must be figured into the equation.
They also have a weight, and some of them are clunkers. In addition, vehicles
stop and vehicles go. Thus, as a concept, vehicle is part of the problem domain.
A good C# traffic simulator program would necessarily include the class
Vehicle
, which describes the relevant properties of a vehicle. The C#
Vehicle
class would have properties like
dTopSpeed
,
nWeight
, and
bClunker
.
I address the
stop
and
go
parts in Chapters 7 and 8.
Because the class is so central to C# programming, the chapters in Part IV of
this book spelunk the ins and outs of classes in much more detail. This chap-
ter gets you started.
Defining a class
An example of the class
Vehicle
may appear as follows:
public class Vehicle
{
public string sModel; // name of the model
public string sManufacturer; // ditto
public int nNumOfDoors; // the number of doors on the vehicle
public int nNumOfWheels; // you get the idea
}
A class definition begins with the words
public class
, followed by the
name of the class — in this case,
Vehicle
.
Like all names in C#, the name of the class is case sensitive. C# doesn’t
enforce any rules concerning class names, but an unofficial rule holds that
the name of a class starts with a capital letter.
The class name is followed by a pair of open and closed braces. Within the
braces, you have zero or more members. The members of a class are variables
that make up the parts of the class. In this example, class
Vehicle
starts with
102
Part III: Object-Based Programming
12_597043 ch06.qxd 9/20/05 1:53 PM Page 102
the member
string sModel
, which contains the name of the model of the
vehicle. Were this a car, the model name could be Trouper II. Hmm, have you
ever seen or heard of a Trouper I? The second member of this example
Vehicle
class is the
string sManufacturer
. The final two properties are
the number of doors and the number of wheels on the vehicle.
As with any variable, make the names of the members as descriptive as possi-
ble. Although I’ve added comments to the data members, that really isn’t
necessary. The name of each variable says it all.
The
public
modifier in front of the class name makes the class universally
accessible throughout the program. Similarly, the
public
modifier in front of
the member names makes them accessible to everything else in the program.
Other modifiers are possible. Chapter 11 covers the topic of accessibility in
more detail.
The class definition should describe the properties of the object that are
salient to the problem at hand. That’s a little hard to do right now because
you don’t know what the problem is, but you can see where I’m headed here.
What’s the object?
Defining a
Vehicle
design is not the same thing as building a car. Someone
has to cut some sheet metal and turn some bolts before anyone can drive an
actual vehicle. A class object is declared in a similar but not identical fashion
to an intrinsic object.
The term object is used universally to mean a “thing.” Okay, that isn’t too
helpful. An
int
variable is an
int
object. A vehicle is a
Vehicle
object. You
are a reader object. I am an author . . . Okay, forget that last one.
The following code segment creates a car of class
Vehicle
:
Vehicle myCar;
myCar = new Vehicle();
The first line declares a variable
myCar
of type
Vehicle
, just like you can
declare a
nSomethingOrOther
of class
int
. (Yes, a class is a type, and all C#
objects are defined as classes.) The
new Vehicle()
command creates a spe-
cific object of type
Vehicle
and stores the location into the variable
myCar
.
The
new
has nothing to do with the age of
myCar
. My car could qualify for an
antique license plate if it weren’t so ugly. The
new
operator creates a new
block of memory in which your program can store the properties of
myCar
.
In C# terms, you say that
myCar
is an object of class
Vehicle
. You also say
that
myCar
is an instance of
Vehicle
. In this context, instance means “an
example of” or “one of.” You can also use the word instance as a verb, as in
instantiating a
Vehicle
. That’s what new does.
103
Chapter 6: Collecting Data — The Class and the Array
12_597043 ch06.qxd 9/20/05 1:53 PM Page 103
Compare the declaration of
myCar
with that of an
int
variable called
num
:
int num;
num = 1;
The first line declares the variable
num
, and the second line assigns an
already-created constant of type
int
into the location of the variable
num
.
The intrinsic
num
and the object
myCar
are stored differently in memory.
The constant
1
does not occupy memory because both the CPU and the C#
compiler already know what a
1
is. Your CPU doesn’t have the concept of a
Vehicle
. The
new Vehicle
expression allocates the memory necessary to
describe a vehicle to the CPU, to C#, to the world, and yes, to the universe!
Accessing the members of an object
Each object of class
Vehicle
has its own set of members. The following
expression stores the number 1 into the
nNumberOfDoors
member of the
object referenced by
myCar
:
myCar.nNumberOfDoors = 1;
Every C# operation must be evaluated by type as well as by value. The object
myCar
is an object of type
Vehicle
. The variable
Vehicle.nNumberOfDoors
is of type
int
(look again at the definition of the
Vehicle
class). The con-
stant 5 is also of type
int
, so the type of the variable on the right side of the
assignment operator matches the type of the variable on the left.
Similarly, the following code stores a reference to the
string
s describing the
model and manufacturer name of
myCar
:
myCar.sManufacturer = “BMW”; // don’t get your hopes up
myCar.sModel = “Isetta”; // the Urkle-mobile
(The Isetta was a small car built during the 1950s with a single door that
opened the entire front of the car.)
An example object-based program
The simple
VehicleDataOnly
program does the following:
ߜ Defines the class
Vehicle
ߜ Creates an object
myCar
ߜ Assigns properties to
myCar
ߜ Retrieves those values out of the object for display
104
Part III: Object-Based Programming
12_597043 ch06.qxd 9/20/05 1:53 PM Page 104
The code for the
VehicleDataOnly
program is as follows:
// VehicleDataOnly - create a Vehicle object, populate its
// members from the keyboard and then write it
// back out
using System;
namespace VehicleDataOnly
{
public class Vehicle
{
public string sModel; // name of the model
public string sManufacturer; // ditto
public int nNumOfDoors; // the number of doors on the vehicle
public int nNumOfWheels; // you get the idea
}
public class Program
{
// This is where the program starts
static void Main(string[] args)
{
// prompt user to enter her name
Console.WriteLine(“Enter the properties of your vehicle”);
// create an instance of Vehicle
Vehicle myCar = new Vehicle();
// populate a data member via a temporary variable
Console.Write(“Model name = “);
string s = Console.ReadLine();
myCar.sModel = s;
// or you can populate the data member directly
Console.Write(“Manufacturer name = “);
myCar.sManufacturer = Console.ReadLine();
// enter the remainder of the data
// a temp is useful for reading ints
Console.Write(“Number of doors = “);
s = Console.ReadLine();
myCar.nNumOfDoors = Convert.ToInt32(s);
Console.Write(“Number of wheels = “);
s = Console.ReadLine();
myCar.nNumOfWheels = Convert.ToInt32(s);
// now display the results
Console.WriteLine(“\nYour vehicle is a “);
Console.WriteLine(myCar.sManufacturer + “ “ + myCar.sModel);
Console.WriteLine(“with “ + myCar.nNumOfDoors + “ doors, “
+ “riding on “ + myCar.nNumOfWheels
+ “ wheels”);
// wait for user to acknowledge the results
Console.WriteLine(“Press Enter to terminate...”);
Console.Read();
}
}
}
The program listing begins with a definition of the
Vehicle
class.
105
Chapter 6: Collecting Data — The Class and the Array
12_597043 ch06.qxd 9/20/05 1:53 PM Page 105
The definition of a class can appear either before or after class
Program
— it
doesn’t matter. However, you should adopt a style and stick with it. Bonus
Chapter 2 on the CD shows the more conventional technique of creating a
separate
.cs
file to contain each class, but just put the extra class in your
Program.cs
file for now.
The program creates an object
myCar
of class
Vehicle
and then populates
each of the fields by reading the appropriate data from the keyboard. The
input data isn’t checked for legality. The program then spits out the informa-
tion just entered in a slightly different format.
The output from executing this program appears as follows:
Enter the properties of your vehicle
Model name = Metropolitan
Manufacturer name = Nash
Number of doors = 2
Number of wheels = 4
Your vehicle is a
Nash Metropolitan
with 2 doors, riding on 4 wheels
Press Enter to terminate...
The calls to
Read()
as opposed to
ReadLine()
leave the cursor right after
the output string. This makes the user’s input appear on the same line as the
prompt. In addition, adding the newline character
‘\n’
generates a blank line
without the need to execute
WriteLine()
.
Discriminating between objects
Detroit car manufacturers can track each car that they make without getting
the cars confused. Similarly, a program can create numerous objects of the
same class, as follows:
Vehicle car1 = new Vehicle();
car1.sManufacturer = “Studebaker”;
car1.sModel = “Avanti”;
// the following has no effect on car1
Vehicle car2 = new Vehicle();
car2.sManufacturer = “Hudson”;
car2.sModel = “Hornet”;
Creating an object
car2
and assigning it the manufacturer name Hudson has
no effect on the
car1
Studebaker.
In part, the ability to discriminate between objects is the real power of the
class construct. The object associated with the Hudson Hornet can be cre-
ated, manipulated, and dispensed with as a single entity, separate from other
objects, including the Avanti. (These are both classic automobiles, especially
the latter.)
106
Part III: Object-Based Programming
12_597043 ch06.qxd 9/20/05 1:53 PM Page 106
Can you give me references?
The dot operator and the assignment operator are the only two operators
defined on reference types, as follows:
// create a null reference
Vehicle yourCar;
// assign the reference a value
yourCar = new Vehicle();
// use dot to access a member
yourCar.sManufacturer = “Rambler”;
// create a new reference and point it to the same object
Vehicle yourSpousalCar = yourCar;
The first line creates an object
yourCar
without assigning it a value. A refer-
ence that has not been initialized is said to point to the null object. Any
attempt to use an uninitialized reference generates an immediate error that
terminates the program.
The C# compiler can catch most attempts to use an uninitialized reference and
generate a warning at build time. If you somehow slip one past the compiler,
accessing an uninitialized reference terminates the program immediately.
The second statement creates a new
Vehicle
object and assigns it to
yourCar
.
The last statement in this code snippet assigns the reference
yourSpousalCar
to the reference
yourCar
. As shown in Figure 6-1, this has the effect of causing
yourSpousalCar
to refer to the same object as
yourCar
.
The following two calls have the same effect:
// build your car
Vehicle yourCar = new Vehicle();
yourCar.sModel = “Kaiser”;
// it also belongs to your spouse
Vehicle yourSpousalCar = yourCar;
// changing one changes the other
yourSpousalCar.sModel = “Henry J”;
Console.WriteLine(“your car is a “ + yourCar.sModel);
yourCar
Vehicle
Assign value
yourSpousalCar
"Rambler"
Figure 6-1:
The
relationship
between
two
references
to the same
object.
107
Chapter 6: Collecting Data — The Class and the Array
12_597043 ch06.qxd 9/20/05 1:53 PM Page 107
Executing this program would output
Henry J
and not
Kaiser
. Notice that
yourSpousalCar
does not point to
yourCar
; rather, both
yourCar
and
yourSpousalCar
refer to the same vehicle.
In addition, the reference
yourSpousalCar
would still be valid, even if the
variable
yourCar
were somehow “lost” (went out of scope, for example), as
shown in the following code:
// build your car
Vehicle yourCar = new Vehicle();
yourCar.sModel = “Kaiser”;
// it also belongs to your spouse
Vehicle yourSpousalCar = yourCar;
// when she takes your car away . . .
yourCar = null; // yourCar now references the “null object”
// . . .yourSpousalCar still references the same vehicle
Console.WriteLine(“your car was a “ + yourSpousalCar.sModel);
Executing this program generates the output
your car was a Kaiser
, even
though the reference
yourCar
is no longer valid.
The object is no longer reachable from the reference
yourCar
. The object does
not become completely unreachable until both
yourCar
and
yourSpousalCar
are “lost” or nulled out.
At that point — well, at some unpredictable later point, anyway — C#’s
garbage collector steps in and returns the space formerly used by that partic-
ular
Vehicle
object to the pool of space available for allocating more
Vehicles
(or
Students
, for that matter). I say a little more about garbage
collection at the end of Chapter 12.
Classes that contain classes are the
happiest classes in the world
The members of a class can themselves be references to other classes. For
example, vehicles have motors, which have power and efficiency factors,
including displacement. (I suppose a bicycle doesn’t have a displacement.)
You could throw these factors directly into the class as follows:
public class Vehicle
{
public string sModel; // name of the model
public string sManufacturer; // ditto
public int nNumOfDoors; // the number of doors on the vehicle
public int nNumOfWheels; // you get the idea
public int nPower; // power of the motor [horsepower]
public double displacement; // engine displacement [liter]
}
108
Part III: Object-Based Programming
12_597043 ch06.qxd 9/20/05 1:53 PM Page 108
However, power and engine displacement are not properties of the car. For
example, my son’s Jeep comes with two different motor options with drasti-
cally different horsepower. The 2.4-liter Jeep is a snail while the same car out-
fitted with the 4.0-liter engine is quite peppy.
The motor is a concept of its own and deserves its own class, as follows:
public class Motor
{
public int nPower; // power [horsepower]
public double displacement; // engine displacement [liter]
}
You can combine this class into the
Vehicle
as follows:
public class Vehicle
{
public string sModel; // name of the model
public string sManufacturer; // ditto
public int nNumOfDoors; // the number of doors on the vehicle
public int nNumOfWheels; // you get the idea
public Motor motor;
}
Creating
myCar
now appears as follows:
// first create a Motor
Motor largerMotor = new Motor();
largerMotor.nPower = 230;
largerMotor.displacement = 4.0;
// now create the car
Vehicle sonsCar = new Vehicle();
sonsCar.sModel = “Cherokee Sport”;
sonsCar.sManfacturer = “Jeep”;
sonsCar.nNumOfDoors = 2;
sonsCar.nNumOfWheels = 4;
// attach the motor to the car
sonsCar.motor = largerMotor;
From the
Vehicle
, you can access the motor displacement in two stages. You
can take one step at a time, as this code shows:
Motor m = sonsCar.motor;
Console.WriteLine(“The motor displacement is “ + m.displacement);
Or, you can access it directly, as shown here:
Console.Writeline(“The motor displacement is “ + sonsCar.motor.displacement);
Either way, you can only access the
displacement
through the
Motor
.
109
Chapter 6: Collecting Data — The Class and the Array
12_597043 ch06.qxd 9/20/05 1:53 PM Page 109