Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is polymophism working in Python if parent constructor is not invoked (unlike Java)?

So, parent class constructor is called in Java, but not in Python. If that means that parent object is not created, how is call to def function in Python successful - What is happening here?

Python code

class Parent:
    def __new__(self):
        print(f"I am the real parent constructor Hahahah {self}")
        return object.__new__(self)

    def __init__(self):
        print(f"I am the constructor of parent {self}")

    def function(self):
        print(f"I am parent's member function and my self value is {self}")

    def over(self):
        print(f"I am parent's O-function and my self value is {self}")

class Child(Parent):
    def __new__(self):
        print(f"I am the real chid constructor Hahahah {self}")
        return object.__new__(self)

    def __init__(self):
        print(f"I am the initialize of child {self}")

    def over(self):
        print(f"I am the child's member O-function and my self value is {self}")

ch = Child()
ch.over()
ch.function()

Output for above Python code. Note: I am the real parent constructor Hahahah was not printed.

I am the real chid constructor Hahahah <class '__main__.Child'>
I am the initialize of child <__main__.Child object at 0x7f4bb5d997b8>
I am the child's member O-function and my self value is <__main__.Child object at 0x7f4bb5d997b8>
I am parent's member function and my self value is <__main__.Child object at 0x7f4bb5d997b8>

Similar Java code

public class main {

    public static void main(String[] args) {
        Child ch = new Child();
        ch.over();
        ch.function();
    }
}

class Parent {
    Parent () {
        System.out.println("In the parent class constructor | " + this);
    }

    public void function () {
        System.out.println("In the member function of parent | " + this);
    }

    public void over () {
        System.out.println("In the member O-function of parent | " + this);
    }
}

class Child extends Parent {
    Child () {
        System.out.println("I the child class constructor | " + this);
    }

    public void over () {
        System.out.println("In the member O-function of chlid | " + this);
    }
}

Output for the above Java code

In the parent class constructor | code.Child@2a139a55
I the child class constructor | code.Child@2a139a55
In the member O-function of chlid | code.Child@2a139a55
In the member function of parent | code.Child@2a139a55
like image 990
Aayush Agrawal Avatar asked Apr 12 '20 07:04

Aayush Agrawal


People also ask

Does Python call parent constructor?

In Python, constructor of class used to create an object (instance), and assign the value for the attributes. Constructor of subclasses always called to a constructor of parent class to initialize value for the attributes in the parent class, then it start assign value for its attributes.

Does child class always call parent constructor?

That depends on what you mean by "use." If you mean, does the default constructor for a child class call the parent constructor, then yes, it does (more below). If you mean, is a default constructor matching whatever parameters the parent constructor has created automatically, then no, not in the general case.

Which executed first the parent or the child constructor?

The constructor of a base class (class A in your case) is always executed before the constructor of the class you are instantiating (class ConstractorDemo in your case).

Does child class inherit parent constructor?

A parent class constructor is not inherited in child class and this is why super() is added automatically in child class constructor if there is no explicit call to super or this.


1 Answers

Python and Java are different.

In Java, a extending class must always call the parent constructor. To make life easy, if the parent constructor has no arguments, it will be called first automatically. Now, if you were to add an argument to the Java Parent constructor like so:

Parent (int i) {
    System.out.println("In the parent class constructor | " + this);
}

you will find the following compilation error:

There is no default constructor available in 'org.example.Parent'

This makes sense, when constructing Child Java doesn't know what to pass as value i. So we have to manually call the Parent constructor:

Child () {
    super(1);
    System.out.println("I the child class constructor | " + this);
}

Python is less strict. It is still good practice to always call the parent constructor, but Python won't require you to do so. This is because Python is not type safe.

Now let's see what happens if you forget to call the parent constructor:

class Parent:
    def __init__(self):
        self.i = 1
        print(f"I am the constructor of parent {self}")

    def printi(self):
        print(self.i)

class Child(Parent):

    def __init__(self):
        pass

ch = Child()
ch.printi()

An fatal error will occur:

Traceback (most recent call last):
  File "test.py", line 15, in <module>
    ch.printi()
  File "test.py", line 7, in printi
    print(self.i)
AttributeError: 'Child' object has no attribute 'i'

To fix this code you can add the following line to the Child init function:

Parent.__init__(self)

As you noticed, the Parent class was still created (because you could call the function method. This is again because Python is less strict. In python an object can be created without calling the constructor.

like image 142
Sijmen Avatar answered Oct 15 '22 10:10

Sijmen