Как работает полимофизм в Python, если родительский конструктор не вызывается (в отличие от Java)? - PullRequest
6 голосов
/ 12 апреля 2020

Итак, конструктор родительского класса вызывается в Java, но не в Python. Если это означает, что родительский объект не создан, как вызов def function в Python успешен - Что здесь происходит?

Python код

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()

Вывод для выше Python код. Примечание: I am the real parent constructor Hahahah не было напечатано.

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>

Аналогично Java код

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);
    }
}

Выход для указанного выше Java кода

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 Ответ

2 голосов
/ 12 апреля 2020

Python и Java различны.

В Java расширяющий класс всегда должен вызывать родительский конструктор. Чтобы упростить жизнь, если родительский конструктор не имеет аргументов, он будет вызван первым автоматически. Теперь, если вы добавите аргумент в конструктор Java Parent следующим образом:

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

вы обнаружите следующую ошибку компиляции:

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

Это имеет смысл , при построении Child Java не знает, что передать в качестве значения i. Поэтому мы должны вручную вызвать конструктор Parent:

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

Python менее строг. По-прежнему рекомендуется всегда вызывать родительский конструктор, но Python не требует от вас этого. Это потому, что Python не является типобезопасным .

Теперь давайте посмотрим, что произойдет, если вы забудете вызвать родительский конструктор:

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()

Неустранимая ошибка происходит:

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'

Чтобы исправить этот код, вы можете добавить следующую строку в функцию Child init :

Parent.__init__(self)

Как вы заметили, класс Parent был все еще создан (потому что вы могли бы вызвать метод function. Это снова, потому что Python менее строг. В python объект может быть создан без вызова конструктора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...