You briefly saw in Chapter 1 how to declare a new class called HelloWorld. In Chapters 2 and 3, you learned about the built-in primitive types included with C#. Since you have now also learned about control flow and how to declare methods, it is time to discuss defining your own types. Type definition is a core construct of any C# program; this support for classes and the objects created from them is what makes C# an object-oriented language.
This chapter introduces the basics of object-oriented programming using C#. A key focus is on how to define classes, which are the templates for objects themselves.
All the constructs of structured, control-flow-based programming from the previous chapters still apply within object-oriented programming. However, by wrapping those constructs within classes, you can create much larger, more organized programs, significantly increasing maintainability.
One of the key advantages of object-oriented programming is that instead of creating new programs entirely from scratch, you can assemble a collection of existing objects from prior work, extending the classes with new features, adding more classes, and thereby providing new functionality.
Readers unfamiliar with object-oriented programming should read the Beginner Topic blocks for an introduction. The general text outside the Beginner Topics focuses on using C# for object-oriented programming, under the assumption that readers are already familiar with object-oriented concepts.
This chapter delves into how C# supports encapsulation through constructs such as classes, properties, and access modifiers; we covered methods in Chapter 5. Chapter 7 builds on this foundation by introducing inheritance and the polymorphism that object-oriented programming enables.
The key to successful programming today lies in the ability to organize and structure the implementation of complex requirements in large applications. Object-oriented programming provides one of the key methodologies in accomplishing this goal, to the point that it is difficult for object-oriented programmers to envision transitioning back to structured programming, except for the most trivial programs.
The most fundamental construct in object-oriented programming is the class. A group of classes form a programming abstraction, model, or template of what is often a real-world concept. The class OpticalStorageMedia, for example, may have an Eject() method on it that causes a disk to eject from the player. The OpticalStorageMedia class is the programming abstraction of the real-world object of a CD or DVD player.
Classes exhibit the three principal characteristics of object-oriented programming: encapsulation, inheritance, and polymorphism.
Encapsulation allows you to hide details. The details can still be accessed when necessary, but by intelligently encapsulating the details, large programs are made easier to understand, data is protected from inadvertent modification, and code becomes easier to maintain because the effects of a code change are limited to the scope of the encapsulation. Methods are examples of encapsulation. Although it is possible to take the code from a method and embed it directly inline with the caller’s code, refactoring of code into a method provides encapsulation benefits.
Consider the following example: A DVD drive is a type of optical media device. It has a specific storage capacity along with the ability to hold a digital movie. A CD drive is also a type of optical media device, but it has different characteristics. The copy protection on CDs is different from DVD copy protection, and the storage capacity is different as well. Both CD drives and DVD drives are different from hard drives, memory cards, and floppy drives (remember those?). All fit into the category of storage devices, but each has special characteristics, even for fundamental functions such as the supported filesystems and whether instances of the media are read-only or read/write.
Inheritance in object-oriented programming allows you to form “is a kind of” relationships between these similar but different items. It is reasonable to say that a DVD drive “is a kind of” storage media and that a CD drive “is a kind of” storage media, and as such, that each has storage capacity. We could also reasonably say that both have an “is a kind of” relationship with “optical storage media,” which in turn “is a kind of” storage media.
If you define classes corresponding to each type of storage device mentioned, you will have defined a class hierarchy, which is a series of “is a kind of” relationships. The base class, from which all storage devices derive, could be the class StorageMedia. As such, classes that represent CD drives, DVD drives, hard drives, USB drives, and floppy drives are derived from the class StorageMedia. However, the classes for CD and DVD drives don’t need to derive from StorageMedia directly. Instead, they can derive from an intermediate class, OpticalStorageMedia. You can view the class hierarchy graphically using a Unified Modeling Language (UML)–like class diagram, as shown in Figure 6.1.