6

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

1 Answers1

2

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.

Sijmen
  • 477
  • 6
  • 12