Re: [RFC][Discussion] Why can constructors violate LSP?
| From: | Mark Trapp | Date: | Fri, 24 Nov 2023 11:46:20 +0000 |
| Subject: | Re: [RFC][Discussion] Why can constructors violate LSP? | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-121804@lists.php.net to get a copy of this message | ||
On Thu, Nov 23, 2023 at 12:31 Robert Landers <landers.robert@gmail.com> wrote:
>
> Hello Internals,
>
> As you may know, an inherited method cannot reduce the visibility of
> an overridden method. For example, this results in a fatal error
> during compilation:
>
> class P {
> public function hello($name =3D 'world') {
> echo "hello $name\n";
> }
> }
>
> class C extends P {
> private function hello($name =3D 'world') {
> parent::hello($name);
> echo "goodbye $name\n";
> }
> }
>
> However, we can make certain methods private anyway, namely,
> constructors (I haven't gone hunting for other built-in methods yet).
> This is perfectly allowed:
>
> class P {
> public function __construct($name =3D 'waldo') {
> echo "hello $name\n";
> }
> }
>
> class C extends P {
> private function __construct($name =3D 'world') {
> parent::__construct($name);
> echo "goodbye $name\n";
> }
> }
>
> To my somewhat trained eye, this appears to violate the Liskov
> Substitution Principle, for example, this now can have hidden errors:
>
> function create(P $class) {
> return new (get_class($class))();
> }
>
> proven by:
>
> $c =3D (new ReflectionClass(C::class))
> ->newInstanceWithoutConstructor();
>
> create($c);
>
> Even though we thought we knew that the constructor was declared public.
>
> I'd like to propose an RFC to enforce the covariance of constructors
> (just like is done for other methods), to take effect in PHP 9, with a
> deprecation notice in 8.3.x.
>
> I'm more than happy to implement it.
>
> Does anyone feel strongly about this one way or the other?
>
> Robert Landers
> Software Engineer
> Utrecht NL
(Apologies: resending because I used the wrong email address to send
to the list)
Hi Robert,
Liskov and Wing explicitly exempted constructors in their original
paper describing the principle:
http://reports-archive.adm.cs.cmu.edu/anon/1999/CMU-CS-99-156.pdf
> 4.1 Type Specifications
>
> A type specification includes the following information:
>
> - The type's name
> - A description of the type's value space
> - A definition of the type's invariant and history properties
> - For each of the type's methods:
> - Its name;
> - Its signature including signaled exceptions;
> - Its behavior in terms of pre-conditions and post-conditions.
>
> Note that the creators are missing. Omitting creators allows subtypes to =
provide different creators than their supertypes. In addition, omitting cre=
ators makes it easy for a type to have multiple implementations, allows new=
creators to be added later, and re ects common usage: for example, Java in=
terfaces and virtual types provide no way for users to create objects of th=
e type.
(Creators is Liskov's word for constructors, which they later define
in the paper.)
Hope that helps.
- Mark Trapp