Before getting started with this section it is probably of value to offer a bit of perspective/advice. If the topic of object orientation (OO) is new to you don't be surprised if the material seems abstract or opaque. Join the club. Personally, I have not encountered a student who reported or demonstrated immediate and complete understanding of the concepts. Rather, study and time are required to achieve depth and applied dexterity. Four-to-six months of experience working with an OO language is typically required to develop moderate proficiency with OO. However, the fundamentals of the paradigm are reasonably elementary and can be demonstrated with uncomplicated code examples. My advice is to work through the examples in this course and resist the urge to understand everything initially. The concepts will become clearer with time and experience. Enjoy the process and work with confidence while you wait for clarity to gradually, and sometimes abruptly, ensue.
Object orientation is a software development approach that considers the "object" to be the center of attention. In OO, the object is also often referred to as the "first class citizen". Prior to OO, the most common approach to software development was procedural programming in which the procedure was the focus. OO became popular with industry development teams in the 1990's and has since retained its prevailing stature. The paradigm consists of three general activities: object-oriented analysis (OOA), object-oriented design (OOD), and object-oriented programming (OOP). In large software development organizations, the three activities are often performed by different team members. OOA consists of experienced practitioners taking a high-level view of the problem landscape and translating the domain challenges into OO terminology. After the broad perspective has been characterized using OO vocabulary, the OOD activity further refines the general product of OOA into program requirements specifications. Text documents and UML (unified modeling language) diagrams are often used to formally express object-oriented designs. The text and UML representations, the results of the design process, are supplied to the programmers who then develop solutions per the requirements outlined in the design documents.
Let's now look more closely at the characteristics that define OO.
What is an Object?
The two most elemental components of OO are the object and the class. Even though the class must be written before an object can be created from it, I discuss the object first since it is the focus of OO and all operations revolve around the object.
I think an object can best be defined by what it contains. Objects can contain two things, functionality and data. And, oh yes, other objects. Functions and data that are contained within an object are known as "object members". In the image of a class below, notice the eight data members (a.k.a. fields or properties) and the five functions (a.k.a. methods). An object is created from a class which will be discussed shortly.
Functionality means that there are components (sections of code) of the object that perform operation(s) or action(s). In C#, functions are known as methods. An object of type Aircraft may contain methods such as takeoff(), climb(), cruise(), descend(), and land(). The concept of object type is known as a "class" and is discussed in the next section. In code, we access an object's method using the "dot operator". For example, if we have a specific object (a.k.a an instance) named aircraftOne which is of the type Aircraft, the following are examples of accessing the methods using the dot operator: aircraftOne.takeoff(), aircraftOne.land(). In those examples, we are instructing the aircraftOne object to run the code in the method takeoff() and in the method land().
Objects also contain data. The example object built from the Aircraft class may contain data elements such as speed, altitude, capacity, souls on-board, maxFuel, fuelRemaining, maxRange, and maxRangeRemaining. At any given point in time (during program operation), the collective values of an object's data elements represent the object's current "state". This is analogous to the "State of the Union" address during which the President reports the current "state" of the country. The "state" of an object is the current values of its data. Like method access, the dot operator is also used to access data members. So, continuing with the example above, aircraftOne.altitude is the value of the current altitude data.
What is a Class?
In the previous section, an object named aircraftOne was discussed which was of type Aircraft which was called a class. A class is commonly described as a "blueprint". Consider the blueprint of a building. The blueprint is a specification of implementation details but it is not an actual building. Using OO terms, the building itself would be known as the object while the blueprint would be the class.
In OOP, the class (blueprint) is simply a section of code that describes an object (building). The process of creating an object from a class is known as "instantiating" an object. That is, an "instance" of the class is created. Using our example above, Aircraft is a class and aircraftOne is the name of an object created from the Aircraft blueprint. Another object named aircraftTwo could be instantiated from the Aircraft class. aircraftTwo would contain its own "state" as defined by the contents of its data members.
When an object is instantiated, the CLR (JIT complier) allocates memory (RAM) to store that object. When that object is no longer needed, it will be cleared from memory by a process known as "garbage collection". Recall that garbage collection is an automatic process managed by the execution engine. It can be deliberately invoked by the programmer but that is rarely (if ever) needed in C# development. You may have noticed the naming convention applied for classes and objects. In C#, class names use uppercamelcase (a.k.a Pascal case) in which the first letter of every word in the class name is uppercase. Object names use lowercamelcase in which the first letter of the first word is lowercase and the first letter of all subsequent words are uppercase.
In addition to the OO activities of analysis, design, and programming, object orientation is also known for the following attributes: inheritance, polymorphism, and encapsulation. These three attributes are often used as a test to determine if a language can be considered object oriented. That is, if a language possesses all three attributes it is object oriented. The three are generally viewed as the pillars of OO.
Inheritance is possibly the most essential and compelling characteristic of OO. Without it, OO would lose much of its allure. Inheritance consists of defining higher level classes upon which lower level classes can be derived. This approach facilitates reuse of common code. This hierarchical relationship is commonly referred to as parent:child, super-class (or just class):subclass, or base:derived. Let's use our Aircraft class as an example.
In the diagram below which is a UML depiction, the familiar Aircraft class is shown with its eight data members and five methods. There are also two subclasses shown: MilitaryAircraft and CommercialAircraft. They are the more specific types of aircraft. The subclasses "inherit" the data members and methods of the Aircraft class. Each of the subclasses have an additional data member and method. So, both MilitaryAircraft and CommercialAircraft classes have nine data members and and six methods. The data members and methods of the Aircraft class are not shown in the subclasses but they do exist in each subclass.
Naturally, we will encounter more examples of inheritance as we progress through the course. At this point, it is important to understand the basic inheritance that occurs between class and subclass as discussed above. In an upcoming chapter we cover interfaces and see how classes can inherit interfaces.
The second pillar of OO is polymorphism which means "many forms". In OO, this characteristic states that methods with the same name can take many forms. Let's consider the fireWeapon() method of the MilitaryAircraft class. The fireWeapon() method could take many forms having multiple versions of its signature. The method signature can have different forms by varying the number and/or type of parameters that the method can receive.
For instance, one version of the fireWeapon() may take one weapon type (e.g. missile) when the method is called. Another version of the same method may take two weapon types (e.g. missile, rocket). Both methods have the name (fireWeapon()) but the different method signatures as determined by argument number and/or type provide polymorphism. The image below shows three versions (forms) of the fireWeapon() method.
As with all concepts in the course, seeing the upcoming code examples will help clarify the abstract concepts. In the following chapters, we will see examples of constructor methods using polymorphism to achieve a variety of behaviors. By the way, constructors are special methods that are called automatically when an object is created (constructed).
The third pillar of OO is encapsulation which is the most readily understood. Recall that objects contain two things: functionality and data. Encapsulation is the process and result of including both functionality and data within the object. All that the object requires to operate is included within the object itself. There are a number of benefits provided by encapsulation. The first benefit is considered synonymous with encapsulation and that is information hiding. By including data and functionality behind the object walls and controlling what is exposed to the exterior, developers are able to "hide information". This makes life better for the developer, for the code, and for the user.
We have heard the expression "TMI" or "too much information". This is applicable in software engineering when too much detail is exposed to the developer or running code. With over exposure clarity and simplicity are compromised. For example, we fortunately do not need to know the many hundreds of operations and data points required to start a modern automobile. We simply turn the key and the car starts. The voltage, amperage, capacitance, starter metrics, etc. are not "exposed" to the driver. That information is hidden.
Another benefit provided by encapsulation is compartmentalization or modularity. In OO, programmers have the system of packaging functionality and data together which enhances both class development and code maintenance. During the design process, using encapsulation, the OO designer can more naturally envision and plan object architecture and interactions. And, when the code requires modifications or updates, the modular nature of OO makes it more convenient for the code maintainer.
Security is also enhanced by encapsulation. This is closely related to the concept of information hiding since is induced a "need to know" requirement. That is, other code within or interacting with the program only has access to the information they need to know. Back to the starting car example. The driver needs to set the correct voltage and amperage sent from the battery to the starter. However, this is performed securely by the turn of key and information hiding. Not only would it be unnecessarily complex to require the driver to set that data directly, it would expose the car to potential damage if the incorrect settings (data) were set by the driver.
In the next chapter, we will use Visual Studio to construct a C# project.