What overriding means
A subclass inherits its parent's methods. Overriding is what you do when you want to change one of them. If the child class defines a method with the same name as the parent's, the child's version is used for objects of the child class. A Puppy is a Dog, but it sounds different: it says "Yip!" where a plain dog says "Woof!". Instead of inventing a new method name, you redefine bark() on Puppy.
class Dog:
def bark(self):
print("Woof!")
class Puppy(Dog):
def bark(self):
print("Yip!")
Dog().bark()
Puppy().bark()
Woof!
Yip!
Code that holds a dog does not need to know which kind it is. It calls bark(), and the right version runs.
The parent is not changed by this. Dog objects still use the original method, and only Puppy objects get the new one.
How Python decides
Python has no keyword for overriding. There is no override, no virtual, and no required decorator. A method is looked up by name, starting at the object's own class and moving up through its parents. The first class that defines the name wins. Since Puppy defines bark, the search stops there and never reaches Dog.bark.
The flip side is that Python does not check that you really meant to override. If you misspell the name, you simply add a new method and the inherited one stays in charge:
class Puppy(Dog):
def Bark(self):
print("Yip!")
With this class, Puppy().bark() still prints Woof!, because Bark with a capital B is a different name.
Extending instead of replacing
Sometimes you want the parent's behavior plus something more. Inside the override, super() reaches the parent's version:
class Puppy(Dog):
def bark(self):
super().bark()
print("(squeaky)")
Calling bark() on a puppy now prints Woof! followed by (squeaky). This lesson's exercise replaces the behavior fully and does not call super().
The lesson's exercise
The starter code has Dog, whose constructor stores a name and whose bark prints "Woof! I am " plus the name. It also opens class Puppy(Dog): with an empty body, and at the bottom creates buddy = Puppy("Buddy") and calls buddy.bark(). The task is to give Puppy its own bark.
- Write the header. Inside
Puppy, indented, writedef bark(self):. The name matches the parent's method exactly, and it takesselflike any method. - Write the body. Print
"Yip! I am "joined withself.name. The attribute exists becausePuppyhas no constructor of its own and so usesDog.__init__.
A method with only a header is a syntax error, so you cannot run the code between the two steps.
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
print("Woof! I am " + self.name)
class Puppy(Dog):
def bark(self):
print("Yip! I am " + self.name)
buddy = Puppy("Buddy")
buddy.bark()
Yip! I am Buddy
Overriding in other languages
Python's approach is the simplest of the common languages. C# needs virtual in the parent and override in the child. Java treats non-final methods as overridable, with an optional @Override annotation that makes the compiler verify the signature. C++ needs virtual in the parent. In Python and JavaScript, you just define the method again.
Common mistakes
- A different name. Any difference in spelling or capitalization creates a new method instead of an override.
- A different parameter list. Python allows an override with other parameters, but callers that use the parent's form then break. If
Puppy.barkrequired an extra argument, a plainbark()call would raise aTypeError. Keep the parameters compatible. - Forgetting
self. The override is a method like any other and needsselffirst. - Repeating the parent's code. If the override needs most of what the parent does, call
super().bark()rather than copying the lines.
Key takeaways
- Overriding means defining a method with the parent's name in the child class. No keyword is needed.
- Python searches the object's class first, so the child's version wins.
super()reaches the parent's version when you want to extend it.- Misspelling the name silently creates a new method.