Methods and the __init__ Constructor
A base class defines shared attributes and methods; derived classes inherit from it and add their own specialized features.
One Shared Foundation
Suppose a program models people at a school. Teachers and students are different kinds of school members, but both have a name and an age. Instead of defining those common attributes separately in both classes, a base class named SchoolMember can define them once. Teacher and Student can then inherit those shared features and add their own specialized attributes, such as salary or marks.
The base class is the shared foundation. A derived class, also called a subclass, reuses the base class's functionality and can add specialized features. In this example, SchoolMember is the base class, while Teacher and Student are derived classes. A Teacher is therefore a SchoolMember with an additional salary attribute, and a Student is a SchoolMember with an additional marks attribute.
Construction State
What do you think happens?
When a Teacher object is created, which initialization happens first: the SchoolMember initialization or the Teacher-specific initialization?
Reveal answer
Answer: SchoolMember initialization
Teacher.__init__ explicitly calls SchoolMember.__init__ first. The inherited name and age attributes are initialized before Teacher adds its salary attribute.
When a Teacher object is created, Python runs Teacher.__init__. That method explicitly calls SchoolMember.__init__(self, name, age). The parent initialization establishes the inherited name and age attributes. After that call finishes, Teacher initializes its own salary attribute. Calling the parent constructor is important because it ensures that the inherited part of the object is initialized before the subclass adds its specialized state.
Methods That Specialize
A method defined in a base class is available to derived classes. A derived class can also redefine that method. Redefining an inherited method is called overriding: the subclass supplies its own implementation instead of using only the parent's implementation.
SchoolMember defines tell() to display common details. Teacher and Student each define their own tell() method. Inside the Teacher version, the subclass first calls SchoolMember.tell(self), which displays the shared name and age information, and then adds the salary. Student follows the same pattern: it calls the parent tell() method and then adds marks.
Method overriding means that a derived class redefines a method inherited from its base class. The parent implementation can still be called from the overridden method with the form ParentClassName.method_name(self).
One Base, Many Behaviors
Teacher and Student both reuse SchoolMember's common attributes and can use its methods. Each subclass then supplies behavior appropriate to its own kind of object. This arrangement reduces code duplication: name, age, and the shared part of tell() are defined in one place rather than repeated in every class.
The same design also supports polymorphism. A loop can contain both Teacher and Student objects and call member.tell() for each one without checking the specific class. Python calls Teacher.tell() for a Teacher object and Student.tell() for a Student object. The method call is the same, but the behavior depends on the object receiving it.
Polymorphism is the ability for the same method call to produce different behavior for different derived classes. It allows code to work with multiple derived classes without knowing each object's specific type.
Mistakes to Avoid
Defining subclass-specific attributes without calling the parent __init__ method.
The inherited name and age attributes are not initialized by the base class.
Fix:
Call SchoolMember.__init__(self, name, age) before adding the Teacher-specific salary attribute.Replacing the parent's method without preserving shared behavior.
The subclass version omits the shared name and age details supplied by the base class.
Fix:
Call the parent tell() method from the overridden method, then add the specialized output.Checking every object's class before calling tell().
The loop does not use the flexibility provided by polymorphism.
Fix:
Call member.tell(); Python selects the appropriate overridden method for the object.
Practice the Trace
Use the SchoolMember, Teacher, and Student design to trace the creation of one Teacher and one Student. For each object, identify which attributes come from SchoolMember, which attribute is added by the derived class, which tell() implementation runs, and what shared behavior is preserved by calling the parent method.
Hints
- Teacher and Student both inherit name and age from SchoolMember.
- Teacher adds salary, while Student adds marks.
- The parent tell() method supplies the shared details before the subclass adds its specialized details.
Tracing a Teacher Object
What happens when Teacher('Mrs. Shrividya', 40, 30000) is created and its tell() method is used?
Start subclass initialization: Python begins by running Teacher.__init__.
Initialize inherited attributes: Teacher.__init__ explicitly calls SchoolMember.__init__(self, name, age), which initializes the name and age attributes.
Initialize the specialized attribute: After the parent initialization completes, Teacher initializes salary.
Run the overridden method: Teacher.tell() calls SchoolMember.tell(self) to display the shared name and age information, then adds the salary.
The Teacher object contains inherited name and age attributes plus its own salary attribute. Its tell() method preserves the base behavior and adds Teacher-specific behavior.
Key Takeaways
- A base class defines attributes and methods shared by related objects.
- A derived class inherits those features and can add specialized attributes and methods.
- A derived class should call the parent __init__ method to initialize inherited attributes.
- Overriding lets a subclass customize a method; calling the parent method lets it extend shared behavior.
- Polymorphism allows one method call, such as member.tell(), to produce the correct behavior for different derived classes.
Key Takeaways
- SchoolMember centralizes the common name, age, and shared method behavior for teachers and students.
- Teacher and Student inherit from SchoolMember and add salary or marks.
- Calling the parent __init__ method initializes the inherited part of a subclass object before subclass-specific attributes are added.
- Overridden methods can call the parent implementation and then add specialized behavior.
- Polymorphism lets the same tell() call work with both Teacher and Student objects.