10
votes

This is a follow-up from this question:

Effective Java 2nd Edition, Item 17: Design and document for inheritance, or else prohibit it:

There are a few more restrictions that a class must obey to allow inheritance. Constructors must not invoke overridable methods, directly or indirectly. If you violate this rule, program failure will result. The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will be invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected.

Since we are only going to touch the initialization aspect of the Java's constructor, I assume it's safe to compare Java's constructor with Python's __init__() in this question.

I am guessing since in Python I have the flexibility to decide when to call (after initializing my current class' data attributes in this case) my ancestor's __init__() as compared to Java where super() needs to be the first statement in a constructor's invocation, I might be safe in calling overridden methods from __init__()?

If I am correct in guessing the aforementioned, wouldn't I as an ancestor class designer getting left at the mercy of my subclass designer? If the subclass designer calls my __init__() before he initializes his data attributes which will be used by one of his overridden methods, and I call that method, I result in program failure!

1
Yes, you can. And I think it's up to the subclass coder to ensure that his subclass initialises things in the right order.Thomas K
I think it's an important concept for sustainable software design - if you just remember the rule not to invoke overridable methods from constructor it'll save you a lot of time in the future. If you violate the rule, everything might work flawlessly, you'll just have to spend more time making sure that it is in fact the case. There are probably a lot of corner cases where violation of this rule is a good idea™.Gleno
"I assume it's safe to compare Java's constructor with Python's init in this question." Bad assumption. They're different languages. With different semantics.S.Lott

1 Answers

5
votes

I might be safe in calling overridden methods from __init__()?

You are. The self binding has already happened before __init__() is evaluated.

ancestor class designer getting left at the mercy of my subclass designer?

That's universally true and has nothing to do with __init__() or anything else.

Subclass developers can do anything. Also, this is Python: they have your source, and can modify that also.

If the subclass designer calls my __init__() before he initializes his data attributes which will be used by one of his overridden methods, and I call that method, I result in program failure!

Correct. The way this will happen is the subclass designer picked a name which you were already using. They assured that the program would fail through their choice of name.