C Primer Plus (5th Edition)
OOP and C# cannot be fully understood if studied in a vacuum. They are both part of a vibrant computer science and programming community. The ideas behind their designs are highly influenced by previous programming paradigms and computer languages. By viewing OOP in the light of preceding programming techniques, it is easier to understand its architecture and the problems it attempts to solve. One of the major predecessors to OOP is process-oriented programming.
Process-Oriented Programming and Its Innate Problems
One of the traditional approaches to the design of computer programs has been the process-oriented style. It prioritizes the actions performed by a software element highly while the data is kept aside, ready to be manipulated by an action. It implies a series of instructions executed one after the other and will most likely contain numerous branching points where only one of several directions is chosen, depending on specific conditions fulfilled in the program. Each instruction more or less resembles a line of pseudocode, as presented earlier in the alien example, and most instructions manipulate data.
In the old fashioned, process-oriented programs, the data can be reached by all parts of the program, as illustrated in Figure 2.2 and can be accessed by any instruction as needed.
Figure 2.2. A program.
Note
Large parts of the source code written in many object-oriented languages, including C#, are constructed using the same primitive language constructs as those used in process-oriented programming. |
This approach is fine for very small projects but, for larger complex programs, the programmer is faced with the formidable task of keeping track of all the different branches belonging to the program because all parts are more or less interconnected. Furthermore, one specific piece of data can be manipulated and changed from all parts of the program. When programming one part of the program, it is difficult to know whether the data you are working with is going to be affected by other parts of the program. The situation will quickly reach chaotic levels (Figure 2.2 already looks pretty chaotic) when several programmers are working together.
Object-Oriented Programming and Its Advantages
How can we attempt to overcome this problem? Well, a typical human way of coping with complexity is to break a problem into simpler pieces. Let's try to break the previous illustration into four smaller, self-contained pieces. The result is displayed in Figure 2.3. We have now separated the whole set of instructions into four separate modules. In the OO world, such modules are called objects. The data has also been divided into four pieces so that each object contains only the data on which it acts. The four objects now collaborate to execute the program by sending messages to each other activating each others' sets of instructions and exchanging data. Not only have we now reduced the complexity of the program considerably, we have also created four self-contained modules, each of which can be "taken out" of the program, modified, and "slotted back" again. With relative ease each module can now be created and maintained by a different programmer.
Figure 2.3. Dividing the process-oriented program into self-contained modules.
As you can see, objects are used to combine data with the methods (instructions) operating on the data. In the object-oriented world, data and processes are given equal importance. But how do we know which objects a program should contain? Which data do we need? Which instructions are necessary? To answer these questions we first need to find out what an object is.
We are surrounded by objects in our daily lives. Examples are books, houses, cars, dogs, people, tables, spiders, plates, and cups. Objects are often able to take part in certain actions. A car, for example, is able to "have its door opened," "have its door closed," "have its engine started," "move forward," "accelerate," "turn," and "brake."
Each object interacts with its surroundings and has an impact on other objects. A "person" object reaching out and opening the door of a "car" object, or a "car" object containing a "person" object transporting him or her from point A to point B, are examples of such interactions. The process-oriented methodology would, if representing a program with cars and people, focus on the actions ("open door," "close door," and so one). Object-oriented programming (OOP), on the other hand, focuses on the "car" object and the "person" object and so it is a methodology emphasizing the objects involved to solve a particular problem.
To illustrate these concepts further, consider the following scenario.
A company, Big Finance Ltd., intends to build a ten-story office building and wants to install an elevator system. Big Finance Ltd. would like to determine the size and number of elevators needed. You, an enthusiastic object-oriented (OO) programmer in a small software company, have been asked to design a program that can simulate the elevator system and thereby answer the company's questions.
New Term: Computer Simulation
A computer simulation attempts to mimic the process of a real-world or theoretical system over time inside a computer. By collecting data from this artificial system, a successful simulation will enable us to gain valuable insights into the real system. Before the simulation can be executed, a model of the system must be designed and implemented on the computer. This model is often a simplified version of the real system, but it is relevant to the insights we want to gain. One of the first computer languages specifically targeted at this problem domain was Simula. Simula is considered to be the first object-oriented programming language because it enabled the programmer to represent abstractions of real-world objects as artificial objects inside a computer simulation program. Simulations and Simula have played an important role in forming the original ideas leading to OOP as we know it today. |
To bridge the gap between the real world and the simulation inside the computer, we must first identify the objects involved. This is typically one of the first steps taken in OOP and relates directly to step 2b of the software development process discussed previously, which segregates each subsystem into objects (modules). Try for a moment to imagine the elevator system in action; which objects are involved? Usually, a good strategy is to notice the nouns you encounter when describing a problem because the nouns identify the objects involved. In this example, we can describe the elevator system as follows with the relevant objects on bolded type.
A number of elevators are located in a building with ten floors. Each elevator can access all floors. When a person wants to get on an elevator, he or she needs to press the button on the floor where he or she is located, and so on.
The next stage relates to step 2c of the software development process where the attributes (data) and behavior (methods) of each module (object) are identified. For example, the "Elevator" object could have the following attributes: a "maximum speed," "current location," "current speed," and "maximum number of people it can contain." Behaviors would include "ascend," "descend," "stop," and "open door." Having identified the relevant attributes and behaviors of each object in the real world, we are ready to represent these in the computer simulation program. To this end, we need to extend our OOP terminology with a few more important terms.
Each part of a C# program that represents an object of the real world is suitably called an object.
The relevant attributes of an object of the real world must be represented in the corresponding object of a C# program. These attributes are then referred to as instance variables, which are said to represent the state of an object. Instance variables are equivalent to the data of Figure 2.3.
The behavior of a real-world object is represented in an object of a C# program in the form of methods. Each method contains instructions similar to those making up the "average-calculating" algorithm presented earlier. The methods of an object act on the instance variables of this same object. Methods are equivalent to the flows of execution in Figure 2.3.
Note
An object in an object-oriented program does not have to represent an object of a physical nature. It can also represent objects of a conceptual nature. Examples of conceptual objects are holiday, computer course, voyage, and spirit. |
Class is another important OOP term. A class specifies the common features (instance variables and methods) of a group of similar objects. Consequently, all objects of the same class have the same instance variables and methods. A programmer is free to choose the instance variables and methods he or she wants to include in a class. These choices all depend on what he or she finds relevant for the particular program he or she is creating.
Let's illustrate the meaning of class with an example. Consider the concept of a car. In the real world, we see, touch, and drive tangible specific cars. Examples could be the blue Volvo in the parking lot with a maximum speed of 100 mph, or the neighbor's black BMW with a maximum speed of 150 mph. Both these tangible cars are referred to as objects.
To enable a description of a particular car object in a C# program, a programmer decides to include the following four instance variables in a class that he or she calls Car: Brand name, Location, Maximum speed, and Current speed (see Figure 2.4). Notice that Color is not included because the programmer found this irrelevant in his or her program. He or she further chooses to equip the class with the methods called Open door, Close door, Move forward, Reverse, Accelerate, Break, and Turn.
Figure 2.4. The class acts as a template for its objects.
Each instance variable of the Car class can be viewed as representing an empty box waiting to be filled out in a specific Car object. Figure 2.4 shows our two cars from above when described through the instance variable templates provided by the Car class.
The content of each instance variable may or may not vary from object to object, as demonstrated in Figure 2.4, but each method defined by the Car class is identical in all Car objects.
The object, class, and their related concepts are introduced at this early stage merely to let your mind gradually get used to the idea of OOP and also as a preparation for the later elaborate and hands-on presentation of these subjects.