Three Fundamental Features of Object-Oriented Programming

 Object-oriented programming languages, such as Python, provide three fundamental features that support object-oriented programming:

  • Encapsulation
  • Inheritance
  • Polymorphism.

Encapsulation

  • Encapsulation in object-oriented programming involves combining instance variables and methods within a class.  
  • It allows certain members of a class to be hidden from external access, known as information hiding or abstraction.  
  • For instance, consider a Fraction object depicted in Figure below.  
  • It has private instance variables (__numerator and __denominator) and 4 public methods.  
  • Private members, indicated by two underscore characters, cannot be directly accessed.  

Ex:  

  • On the other hand, public members can be accessed directly, such as calling getter and setter methods.  
  • In encapsulation, private instance variables of a class are accessed and modified through getter and setter methods.  
  • Getters retrieve the values of the variables, while setters assign new values.  
  • This approach allows control over the values assigned to variables, enabling validation and preventing undesired assignments. By making instance variables private and methods public, encapsulation ensures proper access and manipulation of data within a class. 

Defining Classes in Python 

  • The class keyword is used to define a class in Python.
  • All lines following the class declaration line should be indented.
  • The class contains instance variables, which can be private or public.
  • Instance variables are initialized in the __init__ special method.
  • Class members beginning with two underscore characters are intended to be private members of a class.
  • When attempting to access private members using the regular syntax, such as frac1.__numerator, an AttributeError is raised because the attribute is not found.
  • However, in Python, private members can still be accessed using a mangled name. The mangled name for a private member starts with a single underscore followed by the class name, such as frac1._Fraction__numerator.
  • Unless the variable or method is accessed with its complete (mangled) name, it will not be found.
  • Name mangling prevents unintentional access of private members of a class, while still allowing access when needed.

Example:  

class SomeClass(object):  
    def __init__(self): 
        self.__n = 0 //Private Variable 
        self.n2 = 0 //Public Variable 
obj = SomeClass()

When an attempt is made to access the instance variable __n using obj.__n, an error occurs 

print(obj.__n) 

However, by using the mangled name _SomeClass__n, as shown in obj._SomeClass__n, the private instance variable can be accessed. In this case, it returns the value 0. 

print( obj._SomeClass__n) 

On the other hand, the public instance variable n2 can be accessed directly using obj.n2, and it also returns the value 0. 

print( obj.n2)