Object-Oriented Programming allows you to define new classes from existing classes. This is called inheritance. Inheritance enables you to define a general class (a superclass) and later extend it to more specialized classes (subclasses).
A subclass inherits accessible data fields and methods from its superclass, but it can also have other data fields and methods.
The following concepts play the key role in understanding the Class Inheritance.
If class B inherits class A, every method from class A can be performed in B with the result from class A, unless overridden occurs.
Superclass is also known as base class, parent class; Subclass is also known derived class, child class.
Implementing Inheritance:
# Superclass GeometricObject and Subclasses Rectangle and Circle
# Inheritance classes
# from GeometricObject import GeometricObject
import math
class GeometricObject: # This is the superclass
def __init__(self, color='blue', filled=True):
self.__color = color
self.__filled = filled
def get_color(self):
return self.__color
def set_color(self, color):
self.__color = color
def is_filled(self):
return self.__filled
def set_filled(self, filled):
self.__filled = filled
def __str__(self):
return 'color:' + self.__color + ', filled: ' + str(self.__filled)
class Circle(GeometricObject): # Subclass Circle
def __init__(self, radius):
# Call the __init__ method from the superclass
super().__init__() # Without this line, error will occur
self.__radius = radius
def get_radius(self):
return self.__radius
def set_radius(self, radius):
self.__radius = radius
def get_area(self):
return self.__radius * self.__radius * math.pi
def get_diameter(self):
return 2 * self.__radius
def get_perimeter(self):
return 2 * self.__radius * math.pi
def print_circle(self):
print(self.__str__() + 'radius: ' + str(self.__radius))
class Rectangle(GeometricObject): # Subclass Rectangle
def __init__(self, width=1, height=1):
super().__init__()
self.__width = width
self.__height = height
def get_width(self):
return self.__width
def set_width(self, width):
self.__width = width
def get_height(self):
return self.__height
def set_height(self, height):
self.__height = height
def get_area(self):
return self.__width * self.__height
def get_perimeter(self):
return 2 * (self.__width + self.__height)
def main():
# Input
r = float(input("(Circle) Enter a Radius: "))
w, h = map(float, input("(Rectangle) Enter Width, Height: ").split(","))
# Circle
circle = Circle(r)
print('\\nA Circle', circle)
print("The radius is", circle.get_radius())
print("The area is", circle.get_area())
print("The diameter is", circle.get_perimeter())
# Rectangle
rectangle = Rectangle(w, h)
print("\\nA rectangle", rectangle)
print("The area is", rectangle.get_area())
print("The diameter is", rectangle.get_perimeter())
main()
Output:
(Circle) Enter a Radius: 45
(Rectangle) Enter Width, Height: 35, 60
A Circle color:blue, filled: True
The radius is 45.0
The area is 6361.725123519331
The diameter is 282.7433388230814
A rectangle color:blue, filled: True
The area is 2100.0
The diameter is 190.0
# Superclass DrawingObject, Shape and subclass Rectangle
# Multiple Inheritances
class DrawingObject:
def __init__(self, objectID):
self.objectID = objectID
class Shape:
def __init__(self, color):
self.color = color
class Rectangle(DrawingObject, Shape):
def __init__(self, objectID, color, width=1, height=1):
# Since there are multiple superclasses we need to specify them
# Using super() when there is only one superclass
DrawingObject.__init__(self, objectID)
Shape.__init__(self, color)
self.width = width
self.height = height
def __str__(self):
return f"Rectangle {self.objectID}, color={self.color}, width={self.width}, height={self.height}"
def main():
rectangle1 = Rectangle(123, 'blue', 4, 3)
rectangle2 = Rectangle(124, 'red', 9, 5)
rectangle3 = Rectangle(125, 'orange', 10, 5)
print(rectangle1)
print(rectangle2)
print(rectangle3)
main()
Output:
Rectangle 123, color=blue, width=4, height=3
Rectangle 124, color=red, width=9, height=5
Rectangle 125, color=orange, width=10, height=5
Optional: Private attribute. Inheritance allows a subclass to use the methods and attribute of the superclass. If the attribute in the superclass is declared private, it cannot be accessed directly in the subclass. Thus, there must exist a getter and setter method, or a public method in the superclass to retrieve that attribute.
# Inheritance - Superclass and Subclass
# Use private methods for subclasses
class Rectangle:
def __init__(self, width=1.0, length=1.0):
self.__width = width
self.__length = length
@property
def Length(self):
return self.__length
@Length.setter
def Length(self, length):
self.__length = length
@property
def Width(self):
return self.__width
@Width.setter
def Width(self, width):
self.__width = width
def getArea(self):
return self.__width * self.__length
def getPerimeter(self):
return 2 * (self.__width + self.__length)
class Square(Rectangle):
def __init__(self, width=1.0, length=1.0):
# Inherit width, length to side, side
super().__init__(width, length)
if self.Length != self.Width:
raise ValueError(f"Invalid side of square: {self.Length} != {self.Width}")
# Overridden getArea(self), getPerimeter(self)
def getArea(self):
return self.Length * self.Width
def getPerimeter(self):
# Or 2 * (self.Width + self.Length)
return 4 * self.Length
def main():
s = Square(12, 12)
print("Area:", s.getArea())
print("Perimeter:", s.getPerimeter())
main()