Introduction to Objects

Abstraction

Do you drive? Do you know how a car works?

Do you watch TV? Do you know how to change the channels? Do you know how a TV works?

You don't need to know how a car works to drive a car. You also don't need to know how a TV works to watch a TV (and change the channels).

Programming is similar to driving a car or using a TV in that a programmer doesn't have to know everything about how programs work to be able to write useful programs.

What would programming be like if every time you wanted to calculate a square root, you had to write the square root algorithm from scratch?

Or what if every time you wanted to read the game controller, you had to write all of the code from scratch?

Or what if every time you wanted to use a variable, you had to remember its actual memory address?

Fortunately, we don't have to do these things because somebody else has done the dirty work for us. We don't need to know the memory address of a variable – all we have to do is remember its name. And we don't have to remember the square root algorithm ― all we have to do is remember the name of the square root function (Math.Sqrt). And we don't have to know all of the details for implementing a game controller, all we need to know are the properties and methods of a game controller.

All of the details that are required to solve these problems are still required. However, programmers don't have to worry about the details. Programmers manage those details by hiding them.

One of the problems with trying to write computer programs is the enormous amount of detail that must be managed. A programmer can easily be overwhelmed by all of the details if he doesn't do something to try and limit those details. The tool that programmers use to deal with all of this detail is called abstraction.

Abstraction: the act of separating the essential qualities of an idea or object from the details of how it works (its implementation).

We use a type of abstraction all of the time in everyday life. We don't need to know the "implementation details" of how a car works to drive a car. We know what a car does, but how it does it is unimportant. We don't need to know the "implementation details" of how a television set works to use a television set. In both of these cases, we focus on what we want to do, and don't worry about how it gets done.

Examples of abstraction in programming

Naming abstraction

Naming abstraction is the use of descriptive names to denote variables, constants, procedures, functions, and data types. We don't need to know the actual memory address that is used to store the data in a variable. We don't need to know how many bits are used to represent a variable. We don't need to know the bit pattern used to represent the data (e.g. are characters stored as ASCII, EBCDIC, or UniCode characters). The only thing that we normally need to know is the name that we have chosen for the variable (the what), not its implementation details (the how).

Procedural abstraction

Procedural abstraction is the use of procedure (and function) names to represent the instructions that the procedure is made up of. For example, consider the square root function (Math.Sqrt). It is not necessary for a programmer to know the details of the square root algorithm to be able to calculate square roots in a program. The only thing the programmer needs to remember is the name of the square root function – Math.Sqrt. Procedural abstraction is used in procedures that you write for yourself, too. When you write a procedure, you need to focus on its details. However, once the procedure has been written, you no longer need to focus on its details. All you need to do is remember the name of the procedure, and the next time you need to execute the procedure's instructions, all you need to do is remember the procedure's name and call it.

Data abstraction

Data abstraction is the separation of the properties of a data object from its implementation details. We have been using data abstraction in C# from our very first program.

Integers as examples of abstraction

The integer (int) data type is a data abstraction. The values that an integer variable can take on are approximately -2 billion to +2 billion. The common integer operators are addition (+), subtraction (-), multiplication (*), division (/) and mod (%). Integers are stored in the main memory of most computers as 16-bit or 32-bit twos-complement numbers. But a programmer does not have to know which memory address an integer is stored in, and a programmer does not have to know that integers are stored as 16- or 32-bit twos-complement numbers. All a programmer needs to know is how to declare integers and how to do operations on them. By not having to focus on these implementation details (as a result of the abstraction of the int data type), a programmer can focus on the higher-level details of solving the problem at hand.

When you declare a variable to be an integer, you are creating a specific instance of an integer (e.g. count). And when you declare a second variable to be an integer, you are creating another specific instance of an integer (e.g. sum). Both sum and count take up the same amount of memory, both can have the operations of addition, subtraction, multiplication, division, and mod performed on them, both can represent the same range of data, etc. Even though two different variables have different names, different memory locations, and have different values, they still have all of the characteristics of the integer data type in common. Using object-oriented terminology, the integer data type would be called a Class (a generic data type) and the variables count and sum would be called Objects (specific instances of a class).

Objects and Classes in C#

Consider a familiar object in C# – the SoundEffectInstance. A SoundEffectInstance is an object. An object is a collection of data (called properties) and the functions and procedures (called methods) that manipulate those properties.

The following tables (from the Microsoft web site) list some of the properties and methods of the SoundEffectInstance type.

Public Properties

Name / Description
IsLooped / Gets a value that indicates whether looping is enabled for theSoundEffectInstance.
Pan / Gets or sets the panning for theSoundEffectInstance.
Pitch / Gets or sets the pitch adjustment for theSoundEffectInstance.
State / Gets the current state (playing, paused, or stopped) of theSoundEffectInstance.
Volume / Gets or sets the volume of theSoundEffectInstance.

Public Methods

Name / Description
Pause / Pauses aSoundEffectInstance.
Play / Plays or resumes aSoundEffectInstance.
Resume / Resumes playback for aSoundEffectInstance.
Stop / Overloaded. Stops playing aSoundEffectInstance.

An object is like a structure, but with a few more features added to it.

Property: a value that describes an object

Method: a command that an object "understands".

Object: a data structure that combines data (properties) with procedures and functions (methods) that access and manipulate the data.

Imagine a student record:

struct StudentStruct

{

public string FirstName;

public string LastName;

public string ID;

public float TestAverage;

public float HomeworkAverage;

}

StudentStruct student1;

We can assign values to Student like this:

Student1.FirstName = "George";

Student1.LastName = "Washington";

Student1.ID = "111111111";

Student1.TestAverage = 90.5f;

Student1.HomeworkAverage = 92.0f;

We can also retrieve values from Student1, like this:

Console.WriteLine(Student1.FirstName);

Console.WriteLine(Student1.LastName);

Wouldn't it be nice if a StudentStruct variable "knew" how to do some things, like calculate numeric averages and letter grades? For example, if a StudentStruct variable had a method called TermAverage or LetterGrade? And, even if we changed the TestAverage and the HomeworkAverage, the StudentStruct variable would automatically be able to re-calculate the TermAverage and the LetterGrade.

Of course, there's no reason that we couldn't do something like this:

student1.TermAverage = Average(student1.HomeworkAverage, student1.TestAverage)

And this:

student1.LetterGrade = Grade(student1.TermAverage)

Both of these examples require the addition of two more fields: TermAverage, and LetterGrade. They also require you to write two more functions called Average and Grade.

Objects

There is an alternative: use objects.

When a new data type is combined with a set of well-defined operations on the data (plus a few other features we will talk about later), we call the combination a Class. And variables that are declared to be of this type are called Objects.

A programming language that allows the programmer to build his own objects is called an object-oriented programming language. C# is an example of a programming language that allows programmers to create objects, and therefore, is an object-oriented programming language.

To create a new class (data type) in C#, you must create a Class Module. A class module is simply a file that holds two things:

1.  The declarations of the variables that each object needs.

2.  The code for the methods (functions and procedures) that each object needs.

So, to create a new class, you must do the following:

  1. Create a new Class Module. Choose Project | Add Class from the menu.
  2. Declare the variables (properties) that will be associated with each object. These must be private module-level variables.
  3. Write procedures that control the access to the private variables. You must write a set and get procedure for each property.
  4. Declare the procedures and functions (methods) that will be associated with each object. If these methods are to be accessed by the user of this object (using the "dot" notation), they must be public. If they are not to be used outside of this module, declare them private.

The class module is basically a template for creating variables of the class type. After you have created the class module, you will be able to declare variables (objects) of the class type that you have defined.

Class: a programmer-defined data type that defines properties, methods, and events and is stored in a class module file.

A class is a lot like a structure, except that you can add some features that make it better.

A class is a new data type. As a new data type, you can declare variables of this new data type. Such a variable is called an object.

To create a new class, you must first think about the data items that will be associated with an object of the new class (properties), and the actions that you want to perform on an object of the class (methods). Once you have decided on the properties and methods (and perhaps events) of the class, you can begin to write the class module.

Writing a class module

Before we write our class module, we need to create a project. Create a new Windows Console project called Day20StudentObjects.

Before you can write a class, you need to decide some things about your class:

1.  What data will an object of this class hold? These will be the class's properties.

2.  What commands will an object of this class understand? These will be the class's methods.

In the case of our student class, we will have the following data:

1.  Last name

2.  First name

3.  ID

4.  Homework Average

5.  Test Average

And the following commands:

1.  Term Average (computes the weighted average of the homework and tests).

2.  Letter Grade (computes the letter grade based on the term average).

Once we have decided on the names of our properties and the module-level variables that will be used to hold those property values, we can begin writing our class module. To create a new class module:

·  From the menu, choose "Project" | "Add Class".

·  Choose C# class.

·  Enter the class name (it will be saved in a file with that name and the "cs" suffix).

Adding the member data items

Since each student will have a first name, a last name, an ID number, a homework total, and a test total, we need to declare variables of the appropriate type for each member variable. We will make our variables private.

Add private variables:

private string lastName;

private string firstName;

private string id;

private float homeworkAverage;

private float testAverage;

Private variables are not accessible outside of the file in which they are declared. This improves the security of the data (more later).

Now add public properties:

·  LastName, string, Public Property

·  FirstName, string, Public Property

·  ID, string, Public Property

·  HomeworkAverage, float, Public Property

·  TestAverage, float, Public Property

A property is a value that is accessed by going through two special procedures called get and set. The get procedure allows us to retrieve a property value from an object, and the set procedure allows us to change the value of a property in an object.

Although we haven't been aware of it, every time we have assigned a value to a property in a program we have used the set property procedure of the object, and every time we have retrieved the value of a property in a program we have used the get property procedure of the object. To create a property in C# do the following:

1.  Write a public declaration of the property. For the name of the property, it is common to use the same name as the private variable, but with an upper-case first letter. So the public property that is used to access the private variable named firstName would be FirstName. Although the declaration of a property looks a lot like the declaration of a function, there are no parentheses after the property name.