0% found this document useful (0 votes)
1 views49 pages

Module3-Programming With Inheritance

The document provides an overview of inheritance in object-oriented programming, detailing types such as single, multiple, multilevel, and hierarchical inheritance, along with examples in Python. It also covers concepts like polymorphism, encapsulation, access modifiers, constructors, and the use of self and cls in class methods. Additionally, it discusses the implementation of abstract classes, getters and setters, static methods, and the idea of static classes in Python.

Uploaded by

ooafonrinwo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views49 pages

Module3-Programming With Inheritance

The document provides an overview of inheritance in object-oriented programming, detailing types such as single, multiple, multilevel, and hierarchical inheritance, along with examples in Python. It also covers concepts like polymorphism, encapsulation, access modifiers, constructors, and the use of self and cls in class methods. Additionally, it discusses the implementation of abstract classes, getters and setters, static methods, and the idea of static classes in Python.

Uploaded by

ooafonrinwo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 49

Programming with Inheritance

Understanding Object-Oriented
Programming

Dr. Olaniyan Julius


Inheritance in Programming
Definition: Inheritance allows a new class
(subclass) to derive from an existing class
(superclass).

How It Works: The subclass inherits attributes and


behaviors from the superclass but can also have
unique additions.
Syntax Inheritance
# Define a superclass
class SuperClass:
# Attributes and methods of the superclass
pass

# Define a subclass that inherits from SuperClass


class SubClass(SuperClass):
# Attributes and methods of the subclass
pass
Example of Python inheritance
Classes of Inheritance
• 1. Single Inheritance
– A single child class inherits from one parent class.
# Parent Class
class Animal:
def __init__(self, name):
self.name = name

def make_sound(self):
return "Some generic animal sound"

# Child Class (inherits from Animal)


class Dog(Animal):
def make_sound(self): # Overriding the parent method
return "Bark!"

# Testing Single Inheritance


dog = Dog("Buddy")
Classes of Inheritance
• 2. Multiple Inheritance
• A child class can inherit from multiple parent classes.
# Parent Classes
class Walkable:
def walk(self):
return "I can walk!"

class Swimmable:
def swim(self):
return "I can swim!"

# Child Class (inherits from multiple parents)


class Frog(Walkable, Swimmable):
def croak(self):
return "Ribbit!"

# Testing Multiple Inheritance


frog = Frog()
print(frog.walk()) # From Walkable class
Classes of Inheritance
3. Multilevel Inheritance
• A chain of inheritance where a class inherits from another derived class.
# Base Class
class Animal:
def __init__(self, name):
self.name = name

def make_sound(self):
return "Some animal sound"

# Intermediate Derived Class


class Mammal(Animal):
def has_fur(self):
return "I have fur"

# Further Derived Class


class Cat(Mammal):
def make_sound(self): # Overriding
return "Meow!"

# Testing Multilevel Inheritance


cat = Cat("Whiskers")
print(cat.name) # Inherited from Animal
Classes of Inheritance
4. Hierarchical Inheritance
• Multiple child classes inherit from the same parent.
# Parent Class
class Animal:
def __init__(self, name):
self.name = name

def make_sound(self):
return "Some animal sound"

# Child Classes
class Dog(Animal):
def make_sound(self):
return "Bark!"

class Bird(Animal):
def make_sound(self):
return "Chirp!"

# Testing Hierarchical Inheritance


dog = Dog("Rex")
bird = Bird("Tweety")
Classes of Inheritance
Polymorphism in OOP
• Definition: Polymorphism allows an object of a class to behave like an
object of its subclass.

• Concept: A single function can work with different types, enabling


flexibility.

• Python Implementation: A subclass inherits methods from the parent


class. Methods can be re-implemented to match subclass uniqueness.

• Example: A function func(obj) can take objects of different classes


(e.g., Tomato, Apple) and call their respective type() and colour()
methods, producing different outputs.
Polymorphism in OOP
Code Explanation
• Classes & Methods
• Tomato and Apple classes each define type() and colour().
• Represent different objects but share method names.
• Function func(obj)
• Takes an object as input.
• Calls type() and colour() methods on the object.
• Object Creation & Function Call
• obj_t = Tomato(), obj_a = Apple() → Instances created.
• func(obj_t), func(obj_a) → Same function works for both objects.
• Demonstration of Polymorphism
• func() works with different objects as long as they have type() and
colour().
• One function, multiple object types = Polymorphism!
Types of Polymorphism in Python
Static Polymorphism (Method Overloading)
 Python does not support method overloading like Java or C++.
• However, it can be simulated using default arguments or variable-length
arguments (*args).

• The same method add() works with different numbers of parameters.


Method Overloading
using variable-length arguments (*args).

class Calculator:
def add(self, *args):
return sum(args) # Adds all given numbers

# Testing variable-length arguments


calc = Calculator()
print(calc.add(2, 3)) # Two arguments
print(calc.add(1, 2, 3, 4)) # Four arguments
print(calc.add(10)) # One argument
print(calc.add()) # No argument (defaults to 0)
Dynamic Polymorphism
A subclass overrides a method from the parent class. The method in the
subclass is executed instead of the one in the parent class.
Abstract Classes
An abstract class allows the creation of methods that have common names and
perform similar tasks within child classes. Methods that have been declared but
without any detailed implementations are known as abstract methods.

An abstract class is identified by having a single or multiple abstract methods.


It is useful for designing large functional units. It is also useful in providing a
common interface to implement different components.

With the abstract base class, an application interface (API) can be defined for a
related subclass. This will assist in ensuring that a large code base is organized
and managed well. Also, in case a different programmer or software company
gets involved in providing detailed implementation, having an API will make
things easy.

An abstract class is not built-in in Python. However, ABC is a Python library


that allows the creation of abstract classes through the abstract base classes
(ABC). The method is decorated as abstract with concrete classes as
subclasses. The method is identified with the keyword @abstractmethod.
Abstract Classes Demo
Subclassing
• Subclassing directly from the base is an alternative
way of implementing abstract base classes. This
option avoids explicit declaration of class as an
abstract base class.
Subclassing Code Implementation
ENCAPSULATION
• Wrapping data and the methods into a single
unit (a class) and restricting direct access to
some of the data.

• Why is Encapsulation useful?


• ✅ Protects data from accidental or unauthorized
changes
• ✅ Controls how data is accessed/modified
• ✅ Makes code modular, easier to maintain, and more
secure
How it's done in Python
• Using private/protected members (_var, __var)
• Using getters and setters to control access
class BankAccount:
def __init__(self):
self.__balance = 0 # private variable

def deposit(self, amount):


if amount > 0:
self.__balance += amount

def withdraw(self, amount):


if 0 < amount <= self.__balance:
self.__balance -= amount
else:
print("Invalid withdrawal!")

def get_balance(self):
return self.__balance
Access Modifiers
• In Python OOP, access modifiers are used to
control the visibility of class members
(variables and methods).
• Python has three main access levels, but they
are more of a convention than strict rules like
in some other languages like java, c++, etc.
• Public (Default)
• Protected (Single underscore _)
• Private (Double underscore __)
Access Modifiers
• Public (Default)
• Syntax: Just name it normally, like self.name.
• Access: Can be accessed anywhere, inside or
outside the class.
• Example:
class Person:
def __init__(self):
self.name = "Julius" # Public
Access Modifiers
• Protected (Single underscore _)
• Syntax: Prefix with a single underscore, like
self._age.
• Access: Can be accessed from within the class
and its subclasses (not enforced, just a hint to
programmers).
• Example:
class Person:
def __init__(self):
self._age = 30 # Protected
Access Modifiers
• Private (Double underscore __)
• Syntax: Prefix with two underscores, like
self.__salary.
• Access: Only accessible within the class. Python
"name-mangles" it to _ClassName__variable,
making it harder (but not impossible) to access
from outside.
• Example:
class Person:
def __init__(self):
self.__salary = 5000 # Private
Access Modifiers Summary Table
Constructor
• A constructor is a special method called
__init__() in Python.

• It runs automatically when you create a new


object from a class and is used to initialize the
object's properties.
Basic Syntax of a Constructor
class ClassName:
def __init__(self, parameters):
# initialize properties here
self.property = value
Step-by-Step Example
Step 1: Create the class
class Person:
def __init__(self, name, age): # Constructor
with 2 parameters
self.name = name # Assign the value to the
object
self.age = age
Step-by-Step Example
Step 2: Create an object
p1 = Person("Alice", 25) # This automatically
calls __init__()
Step 3: Access the object’s attributes
print(p1.name) # Output: Alice
print(p1.age) # Output: 25
Default Constructor (No parameters)

class Animal:
def __init__(self):
print("An animal has been created!")

a1 = Animal() # Output: An animal has been


created!
Constructors - Summary
• __init__() is the constructor in Python.
• It is called automatically when an object is
created.
• It’s used to initialize values.
• self refers to the current object.
self
• self is just a convention—
• a name for the first parameter of instance
methods in a class.
• It refers to the specific object (instance) of the
class that is calling the method.
• Think of self as "this object" in other
programming languages like Java or C++.
Why do we need self?
• When you create an object from a class, self lets each object keep track
of its own data.
• Without self, Python wouldn't know which object's data you're referring
to.
class Dog:
def __init__(self, name):
self.name = name # "self.name" is this specific dog's name
def bark(self):
print(f"{self.name} says Woof!")

Then you can do:


d1 = Dog("Bingo")
d2 = Dog("Buddy")

d1.bark() # Output: Bingo says Woof!


d2.bark() # Output: Buddy says Woof!

Without self, both dogs would share the same name—there'd be no way to tell them apart
cls
• Used with class methods, which are declared
with the @classmethod decorator.
• cls lets you access or modify class variables.
class Car:
wheels = 4 # Class variable

@classmethod
def change_wheels(cls, num):
cls.wheels = num

Car.change_wheels(6)
print(Car.wheels) # Output: 6
Class using both self and cls
class Car:
# Class variable (shared across all instances)
total_cars = 0

def __init__(self, model):


self.model = model # Instance variable
Car.total_cars += 1 # Increment class variable

def show_model(self):
# Instance method using self
print(f"Car Model: {self.model}")

@classmethod
def show_total_cars(cls):
# Class method using cls
print(f"Total cars created: {cls.total_cars}")
Class using both self and cls
Usage:
car1 = Car("Tesla")
car2 = Car("BMW")

car1.show_model() # Output: Car Model: Tesla


car2.show_model() # Output: Car Model: BMW

Car.show_total_cars() # Output: Total cars created: 2

• self.model is different for each object (car1, car2).


• cls.total_cars keeps track of how many cars have been created —
shared across all instances.
Name Mangling
• Even though private members (those with
__double_underscores) are intended to be
hidden from outside the class, Python still
allows you to access them using a trick called
name mangling.
class Person:
def __init__(self):
self.__secret = "I love Python“
def reveal_secret(self):
return self.__secret
Name Mangling
• Normal Access (inside the class):
p = Person()
print(p.reveal_secret()) # Output: I love Python

• Trying to access directly (will fail):


print(p.__secret) # Error: AttributeError

• Name Mangling:
print(p._Person__secret) # Output: I love Python

So while private members can be accessed, doing so from


outside breaks the "privacy convention"—use it only if you
really have to (e.g., debugging or testing).
Getters and Setters
• Getters and Setters in Python are used to
access and modify private variables safely.

• Even though we can technically access them


with name mangling, using getters/setters is
the clean and recommended way especially
when we want to add logic when reading or
updating values.
Getters and Setters
class Person:
def __init__(self):
self.__age = 0 # Private variable

# Getter method
def get_age(self):
return self.__age

# Setter method
def set_age(self, age):
if age >= 0:
self.__age = age
else:
print("Age can't be negative.")
Getters and Setters
Using it:
p = Person()
p.set_age(25) # Set the age
print(p.get_age()) # Get the age => 25

p.set_age(-5) # Invalid input => prints


warning
Getters and Setters- Decorators:
Python has a cleaner way using decorators:
@property and @<name>.setter
class Person:
def __init__(self):
self.__age = 0

@property
def age(self): # acts like a getter
return self.__age

@age.setter
def age(self, value): # acts like a setter
if value >= 0:
self.__age = value
else:
print("Age can't be negative.")
Getters and Setters
Now you can use it like this:
p = Person()
p.age = 30 # Setter in action
print(p.age) # Getter in action => 30
p.age = -10 # Invalid => prints warning

• Why Use Getters and Setters?


– To control access to private data
– To add validation (like checking for negative age)
– To log or trigger actions when values change
Static Methods
• A static method belongs to the class, not the
instance (object).
It does not take self or cls as its first
argument.
• Use it when the method doesn't need to
access or modify instance/class data — just
utility logic related to the class.
Example with Static Method
class MathUtils:
@staticmethod
def add(a, b):
return a + b
@staticmethod
def multiply(a, b):
return a * b
print(MathUtils.add(3, 5)) # Output: 8
print(MathUtils.multiply(4, 6)) # Output: 24

Notice: You don't need to create an object! No self is


needed. Just call it directly from the class.
Static Classes
• In Python, there’s no official "static class"
keyword like in C# or Java.

• But you can achieve the same idea using a


class with:

• Only @staticmethods
• No self or object instances
• That makes the class act like a utility class or
namespace.
Static-Class-Like Example
class StringUtils:
@staticmethod
def to_upper(text):
return text.upper()
@staticmethod
def is_palindrome(text):
cleaned = text.replace(" ", "").lower()
return cleaned == cleaned[::-1]

Use it:
print(StringUtils.to_upper("julius")) # Output: JULIUS
print(StringUtils.is_palindrome("madam")) # Output: True
THANK YOU

You might also like