In this section you will learn about Encapsulation and Data Abstraction.
Encapsulation is one of the three pillars of Object Oriented Programming.
The OOP relies heavily on encapsulation.
The terms encapsulation and data abstraction are often interchangeable.
Actually, the data abstraction is achieved through encapsulation.
Encapsulation in general, is a mechanism,
to restrict the direct access of some of objects attributes.
That is, to hide internal implementation of an object, from outside its definition.
Typically access to attributes is only allowed, through setters and getters methods.
We have already used encapsulation in our previous lesson,
without emphasizing on the concept, let’s explore it further here.
Recall our MyClass, in this class, we have set() and get()
instance methods to access the attribute of the class.
set() and get() methods are generally referred as setters and getters.
class MyClass(object): x = 10 def get(self): return self.x def set(self,value): self.x = value
As we have seen in the attributes lesson class or instance attributes can be accessed by using dot notation.
m1 = MyClass() m1.x = 20
Then the question comes, when we access attributes with dot notation why we need setters and getters.
Why setter() and getter() are required ? or why encapsulate?
With the use of get() and set() methods,
We can make sure the attributes are not modified accidentally,
which may lead to inconsistent or invalid state.
With encapsulation we can ensure the integrity of objects data.
Let’s look at an example of why we need setters and getters
class MyNumber(object): def set(self,value): try: value = int(value) except ValueError: return self.value = value def get(self): return self.value def increment(self): self.value += 1 mn = MyNumber() # creating an instance # setter used to set value mn.set(12) # getter is used print(mn.get()) output: 12
Setting the values directly
You know we can set value directly with dot notation.
# set value directly mn.value = 30 mn.increment() print(mn.get()) output: 31 this is as expected, we set a value of 30 and then called increment() method to get 31. This works fine, for <strong>numeric </strong>value. What if we set a <strong>string </strong>value accidentally. # set value directly mn.value = "Hello" # call increment instance method mn.increment() output: --------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-13-61ccc6223a42> in <module>() 30 # call increment instance method 31 ---> 32 mn.increment() 33 34 <ipython-input-13-61ccc6223a42> in increment(self) 16 def increment(self): 17 ---> 18 self.value += 1 19 20 mn = MyNumber() TypeError: must be str, not int
You will be presented with a TypeError.
This is known as breaching the data integrity.
We tried to set a inconsistent data.
Using setter to set the values
What if we use set() method to set inconsistent data, lets check
mn.set("Hello") mn.increment() print(mn.get()) output: 13
as the setter validates the input and discards invalid values.
the data integrity is maintained, and no error is thrown.
Encapsulation ensures safe storage of data in an instance.
As a best practice attributes should always be accessed,
by setter and getter instance methods.
In the next lesson you learn about another important concept Inheritance.