Object Oriented Programming


Object-oriented programming (OOP) is a computer programming model that organizes software design around data, or objects, rather than functions and logic. An object can be defined as a data field that has unique attributes and behavior.


OOP focuses on the objects that developers want to manipulate rather than the logic required to manipulate them. This approach to programming is well-suited for programs that are large, complex and actively updated or maintained. This includes programs for manufacturing and design, as well as mobile applications; for example, OOP can be used for manufacturing system simulation software.


The organization of an object-oriented program also makes the method beneficial to collaborative development, where projects are divided into groups. Additional benefits of OOP include code reusability, scalability and efficiency.


The first step in OOP is to collect all of the objects a programmer wants to manipulate and identify how they relate to each other -- an exercise known as data modeling.


Examples of an object can range from physical entities, such as a human being who is described by properties like name and address, to small computer programs, such as widgets.


Once an object is known, it is labeled with a class of objects that defines the kind of data it contains and any logic sequences that can manipulate it. Each distinct logic sequence is known as a method. Objects can communicate with well-defined interfaces called messages.



What is the structure of object-oriented programming?


The structure, or building blocks, of object-oriented programming include the following:


  • Classes are user-defined data types that act as the blueprint for individual objects, attributes and methods.
  • Objects are instances of a class created with specifically defined data. Objects can correspond to real-world objects or an abstract entity. When class is defined initially, the description is the only object that is defined.
  • Methods are functions that are defined inside a class that describe the behaviors of an object. Each method contained in class definitions starts with a reference to an instance object. Additionally, the subroutines contained in an object are called instance methods. Programmers use methods for reusability or keeping functionality encapsulated inside one object at a time.
  • Attributes are defined in the class template and represent the state of an object. Objects will have data stored in the attributes field. Class attributes belong to the class itself.



Object-oriented programming is based on the following principles:


  • Encapsulation. This principle states that all important information is contained inside an object and only select information is exposed. The implementation and state of each object are privately held inside a defined class. Other objects do not have access to this class or the authority to make changes. They are only able to call a list of public functions or methods. This characteristic of data hiding provides greater program security and avoids unintended data corruption.
  • Abstraction. Objects only reveal internal mechanisms that are relevant for the use of other objects, hiding any unnecessary implementation code. The derived class can have its functionality extended. This concept can help developers more easily make additional changes or additions over time.
  • Inheritance. Classes can reuse code from other classes. Relationships and subclasses between objects can be assigned, enabling developers to reuse common logic while still maintaining a unique hierarchy. This property of OOP forces a more thorough data analysis, reduces development time and ensures a higher level of accuracy.
  • Polymorphism. Objects are designed to share behaviors and they can take on more than one form. The program will determine which meaning or usage is necessary for each execution of that object from a parent class, reducing the need to duplicate code. A child class is then created, which extends the functionality of the parent class. Polymorphism allows different types of objects to pass through the same interface.


Examples of object-oriented programming languages?


Popular pure OOP languages include:


Ruby

Scala

JADE

Emerald



Programming languages designed primarily for OOP include:


Java

Python

C++



Other programming languages that pair with OOP include:


Visual Basic .NET

PHP

JavaScript


Benefits of OOP include:


  • Modularity. Encapsulation enables objects to be self-contained, making troubleshooting and collaborative development easier.
  • Reusability. Code can be reused through inheritance, meaning a team does not have to write the same code multiple times.
  • Productivity. Programmers can construct new programs quicker through the use of multiple libraries and reusable code.
  • Easily upgradable and scalable. Programmers can implement system functionalities independently.
  • Interface descriptions. Descriptions of external systems are simple, due to message passing techniques that are used for objects communication.
  • Security. Using encapsulation and abstraction, complex code is hidden, software maintenance is easier and internet protocols are protected.
  • Flexibility. Polymorphism enables a single function to adapt to the class it is placed in. Different objects can also pass through the same interface.

Classes in Python


A class is considered as a blueprint of objects. We can think of the class as a sketch (prototype) of a house. It contains all the details about the floors, doors, windows, etc. Based on these descriptions we build the house. House is the object.


Since many houses can be made from the same description, we can create many objects from a class.


To create a class, use the keyword class:

class ClassName:
    # class definition


An object is called an instance of a class:

objectName = ClassName()


Example:


class products:
    p_id=""
    p_name=""

p=products()

# We use the . notation to access the attributes of a class. 
p.p_id=1
p.p_name="Apple"

print(p.p_id,p.p_name)


self 

self represents the instance of the class. By using the "self" keyword we can access the attributes and methods of the class in python.


__init__ 

"__init__" is a reseved method in python classes. It is known as a constructor in object oriented concepts. This method called when an object is created from the class and it allow the class to initialize the attributes of a class.


Example:


#Class
class car:
    
    make=""
    model=""
    colour=""

    #Constructor
    def __init__(self,*arg):
        self.make=arg[0]
        self.model=arg[1]
        self.colour=arg[2]
    

#Objects
c1=car("Ford","Mustang","Blue")
c2=car("Chevrolet","Corvette","Yellow")
c3=car("Dodge","Challenger","Red")

print("C1 make:",c1.make)
print("C2 model:",c2.model)
print("C3 model:",c3.colour)



Object Methods

Objects can also contain methods. Methods in objects are functions that belong to the object.


Example:


class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def myfunc(self):
    print("Hello my name is " + self.name)

p1 = Person("John", 36)
p1.myfunc()



Delete Object Properties

You can delete properties on objects by using the del keyword.


Delete Objects

You can delete objects by using the del keyword:


Example:


class products:
    p_id=""
    p_name=""

p=products()
p.p_id=1
p.p_name="Apple"

del p.p_name
print(p.p_id,p.p_name)
del p

print(p.p_id)


Python Inheritance


Inheritance allows us to define a class that inherits all the methods and properties from another class.

Parent class is the class being inherited from, also called base class.

Child class is the class that inherits from another class, also called derived class.



Python super()

The super() builtin returns a proxy object (temporary object of the superclass) that allows us to access methods of the base class.


Example:


# Parent Class
class Animal:
    def __init__(self):
        print("Animals")

    def walks(self):
        print("Animals walk")

# Child Class
class Cat(Animal):
    def __init__(self):
        print("Cat")
        super().__init__()

    def walks(self):
        print("A Cat walks across the street")
        super().walks()

d=Cat()
d.walks()


Class Polymorphism


The word "polymorphism" means "many forms", and in programming it refers to methods/functions/operators with the same name that can be executed on many objects or classes.

Polymorphism is often used in Class methods, where we can have multiple classes with the same method name.


Example: Different classes with the same method


class Car:
  def __init__(self, brand, model):
    self.brand = brand
    self.model = model

  def move(self):
    print("Drive!")

class Boat:
  def __init__(self, brand, model):
    self.brand = brand
    self.model = model

  def move(self):
    print("Sail!")

class Plane:
  def __init__(self, brand, model):
    self.brand = brand
    self.model = model

  def move(self):
    print("Fly!")

car1 = Car("Ford", "Mustang")       #Create a Car class
boat1 = Boat("Ibiza", "Touring 20") #Create a Boat class
plane1 = Plane("Boeing", "747")     #Create a Plane class

for x in (car1, boat1, plane1):
  x.move()


Inheritance Class Polymorphism


What about classes with child classes with the same name? Can we use polymorphism there?


Yes. If we use the example above and make a parent class called Vehicle, and make Car, Boat, Plane child classes of Vehicle, the child classes inherits the Vehicle methods, but can override them:



Example: Create a class called Vehicle and make Car, Boat, Plane child classes of Vehicle


class Vehicle:
  def __init__(self, brand, model):
    self.brand = brand
    self.model = model

  def move(self):
    print("Move!")

class Car(Vehicle):
  pass

class Boat(Vehicle):
  def move(self):
    print("Sail!")

class Plane(Vehicle):
  def move(self):
    print("Fly!")

car1 = Car("Ford", "Mustang") #Create a Car object
boat1 = Boat("Ibiza", "Touring 20") #Create a Boat object
plane1 = Plane("Boeing", "747") #Create a Plane object

for x in (car1, boat1, plane1):
  print(x.brand)
  print(x.model)
  x.move()

Child classes inherits the properties and methods from the parent class.

In the example above you can see that the Car class is empty, but it inherits brand, model, and move() from Vehicle.

The Boat and Plane classes also inherit brand, model, and move() from Vehicle, but they both override the move() method.

Because of polymorphism we can execute the same method for all classes.



public, protected, & private access modifiers in Python


Most object-oriented programming languages, like C++ and Java, have access modifiers that can be used to restrict access to class members (i.e., variables and methods). Access modifiers are usually of three types: public, protected, and private.

Python, however, does not have any such access modifiers that guarantee control over access. In fact, all class variables and methods are public.

Nonetheless, Python does have a convention to imitate access modification where you prefix variable/method names with underscores (_).


Public access


By default, all members (instance variables and methods) are public:


class Person:
    def __init__(self, name, age):
        self.name = name # public
        self.age  = age  # public


Protected access


To make an instance variable or method protected, the convention is to prefix the name with a single underscore _, like:


class Person:
    def __init__(self, name, age):
        self._name = name # protected 
        self._age  = age  # protected


Private access


You can make an instance variable or method private by using the double underscore __, like:


class Person:
    def __init__(self, name, age):
        self.__name = name # private
        self.__age  = age  # private


The __name and __age instance variables cannot be accessed outside the class, doing so will give an AttributeError:


p1 = Person("John", 20)
p1.__name  # will give AttributeError


Example: access modifiers


class Person:
    def __init__(self, name, age, height):
        self.name     = name   # public
        self._age     = age    # protected
        self.__height = height # private

p1 = Person("John", 20, 170)

print(p1.name)        # public: can be accessed
print(p1._age)        # protected: can be accessed but not advised
# print(p1.__height)  # private: will give AttributeError



Scope


A variable is only available from inside the region it is created. This is called scope.


Local Scope


A variable created inside a function belongs to the local scope of that function, and can only be used inside that function.


Example:


def myfunc():
  x = 300
  print(x)

myfunc()


Function Inside Function


As explained in the example above, the variable x is not available outside the function, but it is available for any function inside the function:


Example:


def myfunc():
  x = 300
  def myinnerfunc():
    print(x)
  myinnerfunc()

myfunc()



Global Scope


A variable created in the main body of the Python code is a global variable and belongs to the global scope.

Global variables are available from within any scope, global and local.


Example:


x = 300

def myfunc():
  print(x)

myfunc()

print(x)


If you operate with the same variable name inside and outside of a function, Python will treat them as two separate variables, one available in the global scope (outside the function) and one available in the local scope (inside the function):


x = 300

def myfunc():
  x = 200
  print(x)

myfunc()

print(x)


Global Keyword


If you need to create a global variable, but are stuck in the local scope, you can use the global keyword.

The global keyword makes the variable global.


Example:


def myfunc():
  global x
  x = 300

myfunc()

print(x)