You are on page 1of 15

Module 011 Object-Oriented Programming 2

“Goals and objectives are based on theories and foundations.”


– Abdolkarim Soroush.

In this module, we will continue our exploration in the world of Object-


Oriented Programming (OOP). OOP-based architecture proves to be
beneficial especially when dealing with special types of data which need to
be packaged into one entity. What would you do if you have so much
capability at your hand? Of course, you will use it. This ideology will be
covered in this module together with the principles that surround OOP. Hard
might it be at first, however their important role in OOP’s implementation
will be evident as we discuss each of the principles.

At the end of this module, you will be able to:


1. Identify and differentiate the principles behind OOP.
2. Differentiate assessors from mutators.
3. Differentiate overriding from overloading.
4. Argue the importance of each of the principles in OOP.

Again, researching beyond the coverage of this module is highly encouraged


to supplement your understanding of the topics covered. And as always,
think and see beyond the box.

So, what are we waiting for? Let us continue our exploration of the world of
Computer Programming.

Course Module
Recall

In the previous module, we mainly discussed about the fundamentals of


Object-Oriented Programming. We also discussed about how Object-Oriented
Programming came to be and how it penetrated the world of Programming .
We also discussed about the meaning behind objects in Object-Oriented
Programming and its implications in development. We identified the subsets
of Object-Oriented Programming, namely:
(a) Prototype-based
(b) Class-based
In addition, we discussed the class-based Object-Oriented Programming. We
identified how C++ implemented class-based, through:
(a) Classes
(b) Scopes
(c) Properties
(d) Constructors
(e) Methods
We also identified the different scopes in C++, namely:
(a) Public
(b) Private
(c) Protected
Lastly, we implanted Object-Oriented Programming in C++ through our Box
sample.

Principles in Object-Oriented Programming

Since the last module, we have talked about the world of Object-Oriented
Programming. We covered the essentials of Object-Oriented Programming
which enabled you to write OOP Applications in C++. However, the journey in
the world of OOP does not stop there. There are four (4) principles behind
OOP that you need to learn and how it applies in your current knowledge.
These principles form the core of Object-Oriented Programming. They serve
as the heart of OOP such that without them, OOP is just a simple non-
deterministic programming paradigm.

These four (4) principles are:


(a) Encapsulation
(b) Abstraction
(c) Inheritance
(d) Polymorphism
Note that these principles do not overlay the fundamentals of Object-
Oriented programming discussed in Module010. In fact, these principles both
strengthens and extends those fundamentals to achieve a complete
programming paradigm.

Encapsulation

The principle of encapsulation is to hide the internal workings of your


application. Encapsulation ensures that only the necessary methods and
properties are presented outside of the current class.

This principle is initially enabled using scopes. Remember that there are
three (3) scopes in C++, namely:
(a) Public
(b) Private
(c) Protected
These scopes limit the visibility of the properties and methods from outside
of the class and outside the inheriting class.

In addition to scopes, we have accessors and mutators which limits the


actions done in properties, and by extension, including methods.

Accessors

An accessor is a method within the class that enables the retrieval of values
hidden by scopes. For example, if we hid the property int myID under the
private scope, we cannot access that property from outside of the class. To
let the user, for example, retrieve the value stored in the int myID property,
we can use an accessor.

Before tackling how to write accessors, we need to enumerate several


characteristics of accessors that must be observed. These characteristics are
as follow:
(a) Accessors are methods with the return type like the data type of the
property.
(b) Accessors are parameter-less methods.
(c) Accessors should never assign values to its referenced properties.
(d) Accessors are prefixed with “get” in their function name.
Course Module
As previously discussed, accessors are simply methods that enables the
retrieval of values. Since an accessor is a method for retrieving values, it must
have a non-void return type. Its return type solely depends on the data type
of the hidden property it references. For example, if we have a int myID
under the private scope, its corresponding accessor should have the return
type of int.

Subsequently, accessors are for retrieving values only. Its method


declaration should never contain any parameter since the value to be
returned is not dependent on any other factors aside from the referenced
property itself. Adding parameters to accessors is unnecessary since the
parameter should never affect the value of the referenced property.

In addition, accessors should never assign values to any of the properties,


especially the referenced property. Doing so defeats the purpose of accessors
and might cause a call for integrity checks. An integrity check is a test
conducted to validate the values of properties in classes throughout the
execution of the application. The idea behind integrity checks is to determine
whether there exists a discrepancy between the actual values of the property
and the expected values of the same property.

Lastly, accessors are prefixed with “get” in their function name to indicate
that those methods are indeed accessors. For example, if we are to write an
accessor for our int myID property, its equivalent accessor should be int
getMyID() method.

Implementing Accessors

We will look at a sample implementation of accessors in C++. For this


example, we will be using a variant of our previous Box example back at
Module010. However, we will modify portions of the code to accommodate
changes to showcase the implementation of accessors in C++.
Figure 1. box.h Header File

Figure 1 shows a variant of our box.h header file which has private
properties. In this example, we moved all the properties to private scope.
Because of this, we cannot anymore call any of the properties (e.g. int
length) in our int main() function. To provide read-only access to our
private properties, we implemented accessors.

Figure 2. Class Snippet of box.h

Figure 2 features a snippet of our box.h header file. In this snippet, we have
added a new function under our public scope, the int getLength() method.
Notice that our int getLength() method:
(a) Has a return type of int similar to the data type of Length property,
(b) Does not have any parameter, and
(c) Is prefixed with “get” in the function name.

Course Module
This so far complies with the characteristics of accessors. Now, let us look at
the implementation of our int getLength() method.

Figure 3. Method Snippet of getLength() Method

As shown in Figure 3, our int getLength() method simply returned back


the value of our Length property. There are no other operations done within
the accessor. Hence, we fully completed the characteristics of an accessor.

Mutators

Now that we have a method to retrieve values from our hidden pro perties,
we also have a way to assign values to our hidden properties through
mutators. A mutator is a method within the class that enables the assignment
of values to our properties hidden by scopes. For example, if we hid the
property string Color under the private scope, we cannot anymore assign
values to it directly. In this case, we will be using an intermediary which will
assign values to it – the mutator.

Like our accessors, mutators are bound to several characteristics which help
define their purpose. These characteristics must be keenly observed. These
characteristics are:
(a) Mutators have one parameter.
(b) Mutators may or may not return the final assigned value.
(c) Mutators are prefixed with “set” in their function name.

The main purpose of our mutator is to store values to our hidden properties,
and that only.Therefore, we set only one parameter – the processed or
unprocessed value we will assign to the property. Processed values are values
that have been through several operations which changed the original value
to the current value. Unprocessed values are values which have yet to be
modified.

To better understand the difference between processed and unprocessed


values, we need to look at an example. For example, I have a string value of
“0100” and I want to assign that value to an int variable. As of now, the value
is still unprocessed since it has not yet been through any operation. Now,
when I assign this value to the variable, since the variable is of int data type I
need to convert the value to int. The converted value then becomes our
processed value.

Converting a value from one data type to a different data type is called
“casting”.

In addition, the mutator may or may not return the assigned value. This
solely depends on the developer’s discretion. However, it is advised to return
the value if and only if there were some operations conducted before the
value is assigned to the property. In our previous example of a string value
to be assigned to an int variable, since there will be conversion of data type
about to take place, the resulting int value should be returned. If the value
will be assigned to the property directly without any conversion or
processing, then there is no need to return the value.

Lastly, mutators follow a naming convention to affix “set” in their function


name. This is to convey the use of the method without the need of
documentations and comments.

Implementing Mutators

We looked at an implementation of accessors in our previous


implementation. This time, we will look at a sample implementation of
mutators. For this example, we will use again our example from Module010 –
the Box class.

Course Module
Figure 4. box.h Header File 2

In Figure 4, we look at a variable of the Box class that implements the idea of
both assessors and mutators. Notice we have added a new method void
setColor(string) which, based on the naming convention used, will assign
a value to our string Color property hidden under private scope. Let us
dissect this variant of our Box class.

Figure 5. Class Snippet of box.h Header File 2

In Figure 5, we note that the string Color property is declared under


private scope. This makes the string Color property inaccessible outside
of the class and by the inheriting class. Our added method declaration is
placed under the public scope. This is to ensure that our mutator is
accessible anywhere inside and outside of the class. We have placed one
string parameter under our mutator which is similar in data type with the
concerned property string Color. Let us now look at the implementation of
our mutator.
Abstraction

Another principle in Object-Oriented Programming is the abstraction.


Abstraction is the generalization of classes and types to emphasize their
functionality and interfaces over their implementation and details. This
principle work together with encapsulation since both focuses on making the
internal workings of the classes hidden from outside of the class. This is to
make the class, and its properties and methods to be self-descriptive of their
tasks.

One of the ways to implement abstraction is using scopes. Remember that


the scopes limit the way any other classes and functions interact with the
properties and methods of a class. This way, in the perspective of int main()
for example, can only see the methods under the public scope. Inheriting
classes can see properties and methods both under the protected and
publicscopes.

Inheritance

Third of the four (4) principles in Object-Oriented Programming is the


inheritance. Inheritance is the means to extend the features and
functionalities of existing classes and interfaces. In this principle, there is a
prerequisite of at least one existing class or interface.

An interface is a class in C++ which has methods that are virtual in nature.
Virtual means that the method is not implemented wheresoever inside of the
class. In simpler terms, there is no code blocks under those methods.

Course Module
Figure 6. IBox Interface

In Figure 6, we have implemented an interface called IBox. Notice that IBox


only has two (2) methods and both of which are under the public scope.
These two methods were defined as virtual methods hence there were no
implementations of those methods anywhere in the source code. In addition,
we have added = 0 after the method declaration to signify they are pure
virtual.

A pure virtual method is a method in the class that needs to be implemented


by the inheriting class. Since this class only contain virtual methods, this class
is said to be an interface.
Figure 7. Box Class Inheriting IBox Interface

We have yet another version of our box example shown in Figure 7. In this
Box class, we have inherited the IBox interface we defined in Figure 6.

Notice how we implemented the inheritance through the class declaration


statement class Box : public IBox. In this line, we have inherited all
properties and methods of the IBox interface.

Since the IBox interface contains two (2) pure virtual methods int
getVolume() and string getColor(), we were required to implement the
two methods inside our Box class.

Polymorphism

The last principle of Object-Oriented Programming that we will cover in this


course is polymorphism. Polymorphism is the principle of Object-Oriented
Course Module
Programming that deals with different variations of the same method. These
function uses the same function name. They only differ in the combination of
data types used in their parameters.

For example, we have the sum() function. This function shall accept two (2)
inputs in its parameter. Since we cannot force the use of the sum() function
to be limited to integers only, we need to polymorph the function.

In our sum() function example, we can create several variation of that same
function. If we need to add two integers, we can declare a int sum(int,
int) function. If we need to add two floats, we can declare a float
sum(float, float) function. And if we need to add three integers float
sum(float, float), we can declare int sum(int, int, int) and float
sum(float, float, float) function.

Figure 8. Polymorphing the Sum Function


In Figure 8, we can see four (4) variations of the sum() function. We
supported the combination of two and three parameters for both int and
float data types.

There are two (2) forms of polymorphism, the overriding and the
overloading.

Overriding

Overriding is the polymorphism that occurs during compile time. Overridden


methods are the common structure of polymorphism. It considers the
current form of the functions.

In this type of polymorphism, we have the functions call upon the existing
functions and overlap their statements with another. This is common in
inheriting classes wherein the parent class has an existing method and the
child class overrides that existing method to perform a different set of
functions.

For example, we have a parent IBox interface from Figure 6. In that figure,
the IBox interface has two (2) methods, string getColor() and int
getVolume(). Then in Figure 7, the Box class inherited the IBox interface. In
doing so, Box class also inherited the right to the two (2) methods of IBox
interface. Box class implemented the string getColor() and int
getCVolume() methods. In this case, the two functions of IBox was
overridden by the functions of Box.

Overloading

The second form of polymorphism is overloading. Overloading occurs during


the runtime. In this form of polymorphism, the functions are given different
parameters but share the same function name. These functions usually reside
within the same source code.

Figure 8 implements this form of polymorphism. Notice how the sum()


functions are repeated and structured differently from one another. The first
variation is a sum() function for two integers. The second variation is a sum()
function for three integers. The second variation also called the first variation
of the sum() function. The third variation is a sum() function for two floats.

Course Module
The last variation is like the second variation; the only difference is that the
last variation is for three floats.

Glossary
Abstraction: A principle of Object-Oriented Programming which generalizes
the properties and methods of classes in such a way that the implementation
is hidden from outside the class.
Accessor: A method of a class that returns the value of hidden properties.
Casting: Converting a value of one data type to a different data type.
Encapsulation: A principle of Object-Oriented Programming which groups
the functionalities and statements of certain areas in a code block.
Inheritance: A principle of Object-Oriented Programming which extends the
features and functionalities of existing classes and interfaces.
Integrity Check: Avalidation conducted to verify the integrity of the values
of properties throughout the execution of the application.
Mutator: Amethod of a class that assigns value to hidden properties.
Overriding: Polymorphism that happens during compile time.
Overloading: Polymorphism that happens during runtime.
Polymorphism: A principle of Object-Oriented Programming which allows
multiple variations and versions of the same function sharing the same name.
Processed Value: A value that has undergone a series of operations and
modifications.
Pure Virtual [Method]: A virtual method that must be implemented in the
inheriting classes.
Unprocessed Value: A value that is yet to undergo operations and
modifications.
Virtual [Method]: A method which does not have a body.
References and Supplementary Materials
Books and Journals
Stephen Davis; 2014; Beginning Programming with C++ For Dummies, 2 nd
Edition; United States; For Dummies, A Wiley Brand
Richard Halterman; 2017; Fundamentals of C++ Programming; United States
of America; Southern Adventist University

Online Supplementary Reading Materials


4 Major Principles of Object-Oriented Programming;
http://codebetter.com/raymondlewallen/2005/07/19/4-major-principles-
of-object-oriented-programming/; June 28, 2017
A Brief History of Object-Oriented Programming;
http://web.eecs.utk.edu/~huangj/CS302S04/notes/oo-intro.html; June 26,
2017
Accessors and Mutator Functions in C++; http://ccm.net/faq/29359-
accessors-and-mutators-in-c; June 28, 2017
Programming Paradigms; http://cs.lmu.edu/~ray/notes/paradigms/; June
26, 2017

Course Module

You might also like