I’ve already said that object-oriented programming means defining and building hierarchies of objects and defining their properties and behavior. You can do this to a certain extent in any programming language, just the same as you could, theoretically, take a trip across the Rockies in a golf cart, but it is much easier to do object-oriented programming if you use a language that is designed to support object-oriented programming methods.
Object-oriented programming languages—such as C++ and C#—are characterized by three key features—encapsulation, inheritance, and polymorphism—that support this natural process of identifying and classifying objects.
One of the problems faced by software developers is that the systems we are developing are getting increasingly larger and increasingly more complex. Encapsulation helps by breaking a program down into small, self-contained entities. For example, if you’re building an accounting system, you’ll probably need objects to represent accounts and invoices. Once you’ve developed the Account class, you no longer need to worry about the details of the implementation of the class. You can use the class anywhere in your program in much the same way you would use a built-in type, such as an integer. The class will expose the essential features of the Account object while hiding the implementation details.
The account’s name and the state of its balance are some of the attributes of the object that the client is interested in and needs to know. Details of how the account name is stored—whether it’s an array of 50 characters or a string object, or the fact that the account’s balance is maintained as a currency variable—are irrelevant to the client. The process of hiding the data structures and implementation details of an object from other objects in the system is called data hiding, and it prevents the other objects from accessing details they don’t need to know about. Encapsulation makes large programs easier to comprehend; data hiding makes them more robust.
Objects can interact with other objects through only the publicly exposed attributes and methods of the object. The more attributes and methods publicly exposed, the more difficult it will be to modify the class without affecting the code that uses the class. A hidden variable could be changed from a long to a double without affecting the code that uses objects created (instantiated) from that class. The programmer would have to worry only about the methods in the class that accessed that variable, rather than worry about all the places in the program that an object instantiated from that class might be called.
The natural tendency for humans to classify objects into hierarchies is useful from a programmer’s perspective and is supported in all true object-oriented languages, including C++, by inheritance. Inheritance provides two advantages to the C++ programmer. First, and most important, it lets them build hierarchies that express the relationships between types. Suppose that you have two classes, SavingsAccount and CheckingAccount, both of which are derived from the parent Account class. If you have a function that requires an Account as an argument, you can pass it a SavingsAccount or a CheckingAccount because both classes are types of Account. Account is a general classification, and CheckingAccount and SavingsAccount are more specific types. The second advantage of object-oriented programming is that classes can inherit features from classes higher in the hierarchy. Instead of developing new classes from scratch, new classes can inherit the functionality of existing classes and then modify or extend this functionality. The parent class from which the new class inherits is known as the base class, and the new class is known as the derived class.
One of the major tasks facing developers is finding appropriate classifications for the objects and classes for their programs. For example, if you need to develop classes for a driving game, it makes more sense for you to develop a general car class and then use this class as a base class for specific car types such as Jaguar or Ford. These derived classes would then extend or modify the general car class by adding new attributes and methods or by overriding existing methods. Decomposing objects into subobjects—for example, a car consists of an engine and a chassis—simplifies the development effort. As a result, each of the objects is simpler and therefore easier to design and implement than the collective whole.
The third feature of object-oriented programming languages is polymorphism, which is Greek for “many forms.” It is quite a hard concept to define, so I’ll use some examples to show you what polymorphism is and leave the precise definitions to more academic writers.
Polymorphism essentially means that classes can have the same behavior but implement it in different ways. Consider several different types of vehicle: they all need to be started, so in programming terms, we could say that all vehicles have “start” functionality. Exactly how starting is implemented depends on the vehicle: if it is a Model T Ford, starting will mean cranking the starting handle, but if it is a modern car, starting will mean turning the key in the ignition. If the vehicle is a steam locomotive, starting will be a very different and more complex process.
As another example, consider the SavingsAccount and CheckingAccount types I mentioned earlier. All types derived from Account share certain functionality, such as the ability to deposit, withdraw, and query the balance. They might implement them in different ways because CheckingAccount might permit an overdraft while SavingsAccount might give interest, but they all work the same way. This means that if I’m passed an Account, it doesn’t matter exactly what type of account it is; I can still deposit funds, withdraw funds, and query the balance. This functionality is useful in programming terms because it gives you the ability to work with generic object types—accounts and vehicles—when you’re not concerned with the way in which each class implements functionality.