質問

One of the recommended principles of object-oriented programming is the Liskov substitution principle: a subclass should behave in the same way as its base class(es) (warning: this is actually not a correct description of the Liskov principle: see the PS).

Is it recommended that it also apply to constructors? I mostly have Python in mind, and its __init__() methods, but this question applies to any object-oriented language with inheritance.

I am asking this question because it is sometimes useful to have a subclass inherit from one or more classes that provide some nice default behavior (like inheriting from a dictionary, in Python, so that obj['key'] works for objects of the new class). However, it is not always natural or simple to allow the subclass to be used exactly like a dictionary: it would be sometimes nicer that the constructor parameters only relate to the specific user subclass (for instance, a class that represents a set of serial ports might want to behave like a dictionary with ports['usb1'] being USB port #1, etc.). What is the recommended approach to such a situation? having subclass constructors that are fully compatible with that of their base classes, and generating instances through an object factory function that takes simple, user-friendly parameters? or simply writing a class constructor whose set of parameters cannot be directly given to the constructor of its base classes, but which is more logical from the user perspective?

PS: I misinterpreted the Liskov principle, above: Sven's comment below points out the fact that objects of a subclass should behave like objects of the superclass (the subclass itself does not have to behave like the superclass; in particular, their constructors do not have to have the same parameters [signature]).

役に立ちましたか?

解決

As requested, I post as an answer what previously has been a comment.

The principle as defined in the linked Wikipedia article reads "if S is a subtype of T, then objects of type T may be replaced with objects of type S". It does not read "a subclass should behave in the same way as its base class(es)". The difference is important when thinking about constructors: The Wikipedia version only talks about objects of a subtype, not the type itself. For an object, the constructor has already been called, so the principle doesn't apply to constructors. This is also how I apply it, and the ways it seems applied in the standard lib (e.g defaultdict and dict).

Constructors in multiple inheritance probably can't be discussed in a language-agnostic way. In Python, there are two approaches. If your inheritance diagram includes diamond patterns and you need to make sure all constructors are called exactly once, you should use super() and follow the pattern described in the section "Practical advice" of Raymond Hettinger's article Python's super() considered super. If you don't have diamonds (except for the ones including object), you can also use explicit base class calls for all base class constructors.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top