|
4 | 4 | <qhelp> |
5 | 5 | <overview> |
6 | 6 | <p> |
7 | | -When an instance of a class is initialized, the super-class state should be |
8 | | -fully initialized before it becomes visible to the subclass. |
9 | | -Calling methods of the subclass in the superclass' <code>__init__</code> |
10 | | -method violates this important invariant. |
| 7 | +When initializing an instance of the class in the class' <code>__init__</code> method, calls tha are made using the instance may receive an instance of the class that is not |
| 8 | +yet fully initialized. When a method called in an initializer is overridden in a subclass, the subclass method receives the instance |
| 9 | +in a potentially unexpected state, which may lead to runtime errors from accessing uninitialized fields, and generally makes the code |
| 10 | +more difficult to maintain. |
11 | 11 | </p> |
12 | 12 |
|
13 | 13 | </overview> |
14 | 14 | <recommendation> |
15 | 15 |
|
16 | | -<p>Do not use methods that are subclassed in the construction of an object. |
17 | | -For simpler cases move the initialization into the superclass' <code>__init__</code> method, |
18 | | -preventing it being overridden. Additional initialization of subclass should |
19 | | -be done in the <code>__init__</code> method of the subclass. |
20 | | -For more complex cases, it is advisable to use a static method or function to manage |
21 | | -object creation. |
| 16 | +<p>If possible, refactor the initializer method such that initialization is complete before calling any overridden methods. |
| 17 | +For helper methods used as part of initialization, avoid overriding them, and instead call any additional logic required |
| 18 | +in the subclass' <code>__init__</code> method. |
| 19 | +</p><p> |
| 20 | +If calling an overridden method is required, consider marking it as an internal method (by using an <code>_</code> prefix) to |
| 21 | +discourage external users of the library from overriding it and observing partially initialized state. |
22 | 22 | </p> |
23 | 23 |
|
24 | | -<p>Alternatively, avoid inheritance altogether using composition instead.</p> |
25 | | - |
26 | 24 | </recommendation> |
27 | 25 | <example> |
| 26 | +<p>In the following case, the `__init__` method of `Super` calls the `set_up` method that is overriden by `Sub`. |
| 27 | +This results in `Sun.set_up` being called with a partially initialized instance of `Super` which may be unexpected. |
28 | 28 | <sample src="InitCallsSubclassMethod.py" /> |
29 | | - |
| 29 | +<p>In the following case, the initialization methods are separate between the superclass and the subclass. |
30 | 30 | </example> |
31 | 31 | <references> |
32 | 32 |
|
33 | 33 |
|
34 | 34 | <li>CERT Secure Coding: <a href="https://www.securecoding.cert.org/confluence/display/java/MET05-J.+Ensure+that+constructors+do+not+call+overridable+methods"> |
35 | | -Rule MET05-J</a>. Although this is a Java rule it applies to most object-oriented languages.</li> |
36 | | -<li>Python Standard Library: <a href="http://docs.python.org/library/functions.html#staticmethod">Static methods</a>.</li> |
37 | | -<li>Wikipedia: <a href="http://en.wikipedia.org/wiki/Composition_over_inheritance">Composition over inheritance</a>.</li> |
| 35 | +Rule MET05-J</a>. Reference discusses Java but is applicable to object oriented programming in many languages.</li> |
| 36 | +<li>StackOverflow: <a href="https://stackoverflow.com/questions/3404301/whats-wrong-with-overridable-method-calls-in-constructors">Overridable method calls in constructors<a>.</li> |
38 | 37 |
|
39 | 38 |
|
40 | 39 |
|
|
0 commit comments