Defining Classes
This book hasn’t emphasized the fact, but you’ve been working with classes since the very
beginning. The very first program you created in Lesson 1 included several classes such as
the programs main form and some behind-the-scenes classes that help get the program run-
ning. Since then, you’ve used all kinds of control classes, the
MessageBox class, the Array
class, collection classes, and more. You can even treat primitive data types such as
int and
string as classes under some circumstances.
In this lesson you learn how to create your own classes. You learn how to define a class and
give it properties, methods, and events to make it useful.
WHAT IS A CLASS?
A class defines a type of object. It defines the properties, methods, and events provided by its
type of object. After you define a class, you can make as many instances of that class as you like.
For example, the
Button class defines the properties and behaviors of a button user interface
element. You can create any number of instances of
Buttons and place them on your forms.
You can think of a class as a blueprint for making objects. When you create an instance
of the class, you use the blueprint to make an object that has the properties and behaviors
defined by the class.
You can also think of a class as a cookie cutter. Once you’ve created the cookie cutter, you can
make any number of cookies that all have the same shape.
Classes are very similar to the structures described in Lesson 17 and many of the techniques
you learned there apply here as well. For example, you can give a class fields that the instance
can use to perform calculations.
There are several important differences between structures and classes, but one of the most
important is that structures are value types while classes are reference types. Perhaps the
most confusing consequence of this is that when you assign structure variable
A equal to
23
596906c23.indd 269 4/7/10 12:33:43 PM
270
LESSON 23 Defining Classes
structure variable B, A becomes a copy of B. In contrast, if you assign class variable C equal to
class variable
D, then variable C now points to the same object that variable D does.
For a more detailed discussion of some of these differences, see the section “Structures Versus
Classes” in Lesson 17.
The rest of this lesson focuses on classes and doesnt really talk about structures.
Note that the same techniques apply to structures and classes. For example,
structures have the same benefits as classes described in the following section.
Just because I’m describing them here doesn’t mean I’m trying to imply that
classes are better because they have these advantages that structures don’t.
CLASS BENEFITS
The biggest benefit of classes is encapsulation. A well-designed class hides its internal workings from
the rest of the program so the program can use the class without knowing how the class works.
For example, suppose you build a
Turtle class to represent a turtle crawling across the screen
drawing lines as it moves. The class would need properties such as
X, Y, and Direction to define
the
Turtles location and direction. It might also provide methods such as Turn to make it change
direction and
Move to make it move.
The
Turtle class needs to know how to draw the Turtles path as it moves, but the main program
doesnt need to know how it works. It doesn’t need to know about
Graphics objects, Pens, or the
trigonometric functions the
Turtle uses to figure out where to go. The main program only needs to
know how to set the
Turtles properties and call its methods.
You can download the Turtle example program from the book’s web site as part of
the Lesson23 folder and follow along in its code as you read through this lesson.
Some other benefits of classes (and structures for that matter) include:
Grouping data and code
The code that makes a Turtle move is right in the same object as
the data that determines the
Turtle’s position and direction.
Code reuse
You only need to write the code for the Turtle class once and then all
instances of the class get to use it. You get even more code reuse through inheritance, which
is described in the section “Inheritance” later in this lesson.
Polymorphism
Polymorphism means you can treat an object as if it were from another
class as long as it inherits from that class. For example, a
Student is a type of Person so you
should be able to treat a
Student object as if it were either a Student or a Person. The section
“Polymorphism” later in this lesson describes this further.
596906c23.indd 270 4/7/10 12:33:44 PM
Making a Class
271
MAKING A CLASS
Now that you know a bit about what classes are for, it’s time to learn how to build one.
Making a class in C# is simple. Open the Project menu and select Add Class. Give the class a good
name and click Add.
Initially the class looks something like the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyProgram
{
class Employee
{
}
}
Here MyProgram is your programs default namespace, which by default is the name of your program. It
is used as the namespace for all of the forms and other classes that you add to the program.
Employee is the name that I gave the class in this example.
At this point, the class can’t do anything. You can write code to create an instance of the class but it
will just sit there. To make the class useful, you need to add properties, methods, and events.
Properties
are values associated with a class. For example, an Employee class might define
FirstName, LastName, and EmployeeId properties.
Methods
are actions that an object can perform. For example, an Employee class might provide
a
CalculateBonus method that calculates the employee’s end-of-year bonus based on perfor-
mance during the year.
Events
are raised by the class to tell the rest of the program that something interesting hap-
pened, sort of like raising a flag to draw attention to something. For example, the
Employee
class might raise a
TooManyHours event if the program tried to assign an employee more than
40 hours of work in a week.
Properties, methods, and events allow a program to control and interact with objects. The following
sections explain how you can add properties, methods, and events to your classes.
Properties
If you give a class a public field, other pieces of code can get and set that field’s values. This kind of
variable is called a field. A field is similar to a property but it has one big disadvantage: it provides
unrestricted access to its value. That means other parts of the program could dump any garbage into
the field without the class being able to stop them.
In contrast, a class implements a property by using accessor methods that can include code to protect
the class from garbage values. You’ll learn more about this as you see how to build properties.
596906c23.indd 271 4/7/10 12:33:44 PM
272
LESSON 23 Defining Classes
The following sections describe the two most common approaches for implementing properties:
auto-implemented properties and backing fields.
Auto-Implemented Properties
The easiest way to make a property is to use an auto-implemented property. The syntax for an
auto-implemented property is:
accessibility dataType Name { get; set; }
Here accessibility determines what code can use the property. It can be public, private, and so
on. The
dataType determines the property’s data type and Name determines its name. The get and
set keywords indicate that other code should be able to get and set the property’s value.
You can omit the set clause to create a read-only property.
The following code creates a simple property named X of type int.
public int X { get; set; }
Creating an auto-implemented property is almost as easy as making a field, but it’s a tiny bit more
work, so why should you bother?
Making an auto-implemented property sets up the code so it will be easy to upgrade the property to
use more complicated code later. For example, suppose you decide that the
Turtle class’s Direction
method should only allow angles between 0 and 259 degrees. In that case you can convert the auto-
implemented property into a property built using a backing field as described in the next section.
Backing Fields
When you make an auto-implemented property, C# automatically generates accessors that let you
get and set the property’s value. You can use those accessors without needing to know the details of
how they work.
When you make a property that is not auto-implemented, you need to write the accessors yourself.
The following shows the basic syntax used to define a property that is not auto-implemented:
accessibility dataType Name
{
get
{
...getCode...
}
set
{
...setCode...
}
}
596906c23.indd 272 4/7/10 12:33:44 PM
Making a Class
273
Here accessibility, dataType, and Name are the same as before. The getCode and setCode are
the pieces of code that get and set the property’s value.
One common way to implement this kind of property is with a backing field. A backing field is a
field that stores data to represent the property. The
getCode and setCode use the field to get and
set the propertys value.
The following C# code shows a version of the
Direction property stored in the backing field named
direction:
// The Turtle’s direction in degrees.
private int direction = 0; // Backing field.
public int Direction
{
get { return direction; }
set { direction = value; }
}
The code starts by defining the field direction to hold the property’s value. The field is private so
only the code inside the class can see it.
The property’s
get accessor simply returns the value of direction.
The property’s
set accessor saves a new value in the backing field direction. The new value that the
calling code is trying to assign to the property is stored in a parameter named
value. This parameter is
a bit odd because it isn’t declared anywhere. The
set accessor implicitly defines value and can use it.
The preceding code simply copies values in and out of the backing field, so why did you bother?
There are several reasons.
First, a property hides its details from the outside world, increasing the class’s encapsulation. As far
as the outside world is concerned, a description of the
Direction property tells you what is stored
(the direction in degrees) but not how it is stored (as an integer value in degrees).
This example stores the direction in degrees but suppose you decided that the class would work better if
you stored the direction in radians. If
Direction is a field, then any code that uses it would now break
because it is using degrees. If you use accessors, they can translate between degrees and radians as
needed so the code outside the class doesn’t need to know that anything has changed.
The following code shows a new version of the
Direction property that stores the value in radians.
As far as the code outside the class is concerned, nothing has changed.
// The Turtle’s direction in radians.
private double direction = 0; // Backing field.
public int Direction
{
get { return (int)(direction * 180 / Math.PI); }
set { direction = value * Math.PI / 180; }
}
You can also add validation code to property accessors. For example, suppose the Direction property
represents an angle in degrees and you only want to allow values between 0 and 359. The following
596906c23.indd 273 4/7/10 12:33:45 PM
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.124.177