Is it correct to access variables from a child class in a parent class? Is this a good OOP approach? I don't need to create instances of Animal class, but if I will, the make_sound
method will raise AttributeError
, which is bothering me.
class Animal:
def make_sound(self):
print(self.sound)
class Cat(Animal):
sound = 'meow'
class Dog(Animal):
sound = 'bark'
cat = Cat()
cat.make_sound()
dog = Dog()
dog.make_sound()
The reference holding the child class object reference will not be able to access the members (functions or variables) of the child class. This is because the parent reference variable can only access fields that are in the parent class.
The parent class can hold reference to both the parent and child objects. If a parent class variable holds reference of the child class, and the value is present in both the classes, in general, the reference belongs to the parent class variable. This is due to the run-time polymorphism characteristic in Java.
Classes called child classes or subclasses inherit methods and variables from parent classes or base classes. We can think of a parent class called Parent that has class variables for last_name , height , and eye_color that the child class Child will inherit from the Parent .
There's nothing inherently wrong with this approach. It really depends on the scope and significance of this class, and where its being used. Building a parent class to use implicitly defined attributes is quick, and in many cases perfectly OK. But, sometimes those implicit attributes can get out of hand, and you might want to ensure that anyone making new subclasses has to define those attributes.
There are a couple approaches to this. Some of this may not work depending on what version of Python you are using. I believe the usage of ABC like this works in Python 3.4+.
Python (and many OO languages) have the concept of an Abstract Base Class. This is a class that can never be instantiated, and it enforces that any subclasses must implement methods or properties defined as abtract in order to be instantiated.
Here's how you could provide a make_sound
method, and still be 100% sure that anyone subclassing Animal is indeed making that sound.
from abc import ABC, abstractmethod
class Animal(ABC):
def make_sound(self):
print(self.sound)
@property
@abstractmethod
def sound(self):
""" return the sound the animal makes """
class Dog(Animal):
@property
def sound(self):
return "bark"
class Cat(Animal):
sound = "meow"
class Thing(Animal):
""" Not an animal """
dog = Dog()
dog.make_sound()
cat = Cat()
cat.make_sound()
# thing = Thing() this will raise a TypeError, complaining that its abstract
# animal = Animal() as will this
This shows the many different ways to do this. Using the @property
decorator allows you to set instance variables, or more complex logic, that affect it. Setting sound in the class is (somewhat) like setting a static member in a Java class. Since all cats meow, this probably makes sense in this case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With