Object Oriented Programming (OOP) is an important concept to understand as a software developer. Most of the software you will encounter or work with will employ OOP in some way.
There are many concepts that are derived from OOP and encapsulation is one of them. The focus of this post will be about encapsulation and the various ideas behind it.
Encapsulation
Encapsulation is an OOP concept that binds together the data and functions that manipulate the data. It also keeps both safe from outside interference and misuse. The encapsulation of data leads to another important concept in OOP, which is data hiding.
Data encapsulation is a mechanism of bundling data and the functions that use them. Ideally, all the data and implementations should be hidden. However, there are times in which it is necessary for the outside to interact with the encapsulated data. An example of encapsulation is classes. A class often contain private, protected and public member variables and functions.
Data Abstraction
Data abstraction is the answer to allowing the outside to communicate with encapsulated data. Data abstraction is a mechanism of exposing only the interfaces and hiding the implementation details from the user.
An example of an interface is a public member function of a class. It is accessible to an object outside of the class. The outside object can use the function to interact with the class.
Interfaces
Interfaces are usually functions that are exposed by encapsulated data to allow interactions with the outside world. By allowing communication only through interface functions, it prevents the outside world from having direct access to the data. The underlying implementation is also hidden from the outside world.
In order for interfaces to work well, the user must have a clear idea of what each interface does. This means each interface must be well documented.
Example
For this example, I will be using C++ to demonstrate data encapsulation and data abstraction. The class is a rectangle class and will have hidden data for its size. The class will provide interfaces for the outside world to change the dimension and get the perimeter and area.
#include <iostream> /** * Rectangle class which encapsulates data. It has interfaces for the outside * to communicate with it. */ class Rectangle { private: // hidden from outside double width; double length; protected: public: Rectangle() :width(0.0), length(0.0) { // do nothing } Rectangle(double width, double length) :width(width), length(length) { // do nothing } /** * Interface to change the width. */ void setWidth(const double & new_width) { width = new_width; } /** * Interface to change the length. */ void setLength(const double & new_length) { length = new_length; } /** * Interface to get the width. */ double getWidth() { return width; } /** * Interface to get the length. */ double getLength() { return length; } /** * Interface to get the area. */ double computeArea() { return width * length; } /** * Interface to get the perimeter. */ double computePerimeter() { return 2.0 * (width + length); } }; int main(int argc, char** argv) { double width = 10.0; double length = 15.0; Rectangle rectangle(width, length); std::cout << "Length = " << rectangle.getLength() << ", Width = " << rectangle.getWidth() << "\nArea = " << rectangle.computeArea() << ", Perimeter = " << rectangle.computePerimeter() << std::endl; double new_width = 12.0; double new_length = 9.0; rectangle.setLength(new_length); rectangle.setWidth(new_width); std::cout << "Changing length and width of rectangle." << std::endl; std::cout << "Length = " << rectangle.getLength() << ", Width = " << rectangle.getWidth() << "\nArea = " << rectangle.computeArea() << ", Perimeter = " << rectangle.computePerimeter() << std::endl; return 0; }
Compiling the code and executing it will produce the following result:
Length = 15, Width = 10 Area = 150, Perimeter = 50 Changing length and width of rectangle. Length = 9, Width = 12 Area = 108, Perimeter = 42
The example initializes the Rectangle class with a length and width then computes the area and perimeter all through interfaces by the rectangle class. Then through the public member interfaces, setWidth and setLength, the outside world changes the dimension of the rectangle and recomputes its area and perimeter. Notice that the implementation and the data of the dimension are hidden from main.
I hope you found this post helpful. If you found this post helpful, share it with others so they can benefit too.
What do you find to be the most challenging with object oriented programming?
To stay in touch, follow me on Twitter, leave a comment, or send me an email at steven@brightdevelopers.com.