Prevent certain attributes to be inherited in child class

Need some help to solve this puzzle folks:

When creating a child class in Python and defining the init method, I would like to import all the attributes of the super/parent class except certain positional parameters and certain parameters (which are not defined inside parent classes' init method's list of positional or keyworded/non-keworded parameters but) defined within/inside the parent class init method with a default value.

Is there a way to prevent/avoid certain/specific parent class attributes to be imported in the child class upon initiation? I am aware that we can override methods in the child class which do not mimic parent class behaviors, but I am not aware how to do the same with attributes, so I was thinking if I could avoid them completely!

I will give an example of why I need a certain child class to mimic everything from its parent except certain attribute.

Consider a parent class "Car". The child class will be "ElectricCar". The parent class has an attribute defined called "liters_gasoline" with certain integer as its default value.

Now, I would like to inherit everything in the ElectricCar sub-class except that "liters_gasoline" parameter, because ElectricCars don't use fuel/gasoline. How to prevent this "liters_gasoline" parameter from being inherited in the child class? I don't want this parameter in child class!

How to do this?

Upvotes: 4

Views: 3859

Answers (4)

Jay Solanki
Jay Solanki

Reputation: 1

One of the solutions that I found is.. like I don't know it is accurate or not.. but it works. eg. you have

class Person:
    def __init__(self, name, age, height):
        self.name = name
        self.age = age
        self.height = height

class Dog(Person):
    def __init__(self, name, age, color, owner):
        super().__init__(name, age, 0)
        self.color = color
        self.owner = owner

Upvotes: 0

Sumedha Rana
Sumedha Rana

Reputation: 1

If something inherits from a parent class it should have all the attributes of the parent class.

Upvotes: 0

Niel Godfrey P. Ponciano
Niel Godfrey P. Ponciano

Reputation: 10699

You are violating at least 2 principles there:

1. Interface segregation principle - fat interfaces

If you decide to define liters_gasoline within the base class Car, remember that:

no client should be forced to depend on methods it does not use.

Your plan is basically an example on how to contradict this rule. You are designing a fat interface, where your base class Car requires you to have the liters_gasoline and then later on, your subclass ElectricCar doesn't need it as it shouldn't be part of its characteristics.

when an interface incorporates too many operations on some data into an interface, only to find that most of the objects cannot perform the given operations.

In analogy, I believe one of the more commonly known examples of this is designing a base class Bird with the functionality of fly which of course works for a subclass Eagle but not for a subclass Penguin.

2. Liskov substitution principle

If you decide to delete liters_gasoline within the subclass ElectricCar, remember that:

if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e., an object of type T may be substituted with any object of a subtype S) without altering any of the desirable properties of the program

Since you deleted the property liters_gasoline of S (ElectricCar), are you confident that it could still replace all objects of type T (Car). The answer is no. Why?

Let's say I'm performing the following:

print(T.liters_gasoline)

And I substitute S to that T:

print(S.liters_gasoline)  # Error, attribute doesn't exist.

Which means that your subtype S (ElectricCar) can't anymore be substituted to all types of T (Car).

Solution

As @joey mentioned, redesign your interface (base class Car) to only include properties that are common for all types of Car.

Should there be any unavoidable instances where your subclass doesn't need a particular attribute of the base class (most of the time is a clue that you have a fat interface), you can choose to just nullify its value e.g. self.some_attr_in_base = None if you think a redesign wouldn't be necessary.

  • Some may view this as an anti-pattern, but sometimes it is all that is needed. Even Django supports this stating "Fields inherited from abstract base classes can be overridden with another field or value, or be removed with None."

Related references:

Upvotes: 2

joey
joey

Reputation: 115

If something inherits from a parent class it should have all the attributes of the parent class. For example "liters_gasoline" should only be in the class of a gasoline car not an electric car.

Upvotes: 2

Related Questions