On Wednesday 06 August 2025 13:41:14 (+02:00), Rob Landers wrote:
>
>
> On Wed, Aug 6, 2025, at 13:26, Hans Krentel wrote:
> >
> >
> >
> > On Sunday 03 August 2025 11:30:13 (+02:00), Rob Landers wrote:
> >
> > > I'm not sure that this is a bug. You can redeclare the same type and
add
> > hooks (or change them), which breaks all assumptions about
> > substitutability.
> >
> > Rob, maybe you can lecture me a bit: Isn't substitutability on the
public
> > interface / protocol only? What am I not seeing in your example?
>
> From a child class's perspective, the "public interface" is both
protected + public of the parent. If you change or misuse a parent's
implementation or invariants, it violates LSP, even if it doesn't affect
external clients immediately.
Ah okay, that part is not in my book, this explains to me why in your
example it violates substitutability for you, and with that thinking it
also prevents or degrades implementability for me so to say, as otherwise I
could not make use of visibility in classes - it would take away that tool
from me or I would not treat it well, potentially leading to defects in the
program.
>
> Take for example:
>
> class Fruit {
> public string $kind { get => "fruit" }
> }
>
> class Vegetable extends Fruit {
> public string $kind { get => "vegetable" }
> }
>
> function foo(Fruit $fruit) {}
>
> foo(new Vegetable); // hmmm
>
> This is a "soft" violation that only makes sense to us humans, but PHP
allows it. It requires us humans to realize we are performing an LSP
violation and refactor the code so that we don't pass a Carrot to someone
expecting a Mango.
Thankfully in this example it is all public, but I definitely would say
this is not an LSP violation, just saying.
>
> This can be done through protected means as well (simply replace the
properties above as protected properties used internally), and it won't be
as obvious to consumers outside the class, but still there, nonetheless.
>
Okay, this is it probably just like above (for me): When $kind would be
protected, it would not be part of the public protocol, and the
substitutability test with the PHP runtime would still pass for the
foo(Fruit) event with a Vegetable that is a Fruit (extends). That would be
a test for substitutability, per the PHP runtime guarantees (it returns
successfully after sending the message), it does not break the program:
>> an object (such as a class) may be replaced by a sub-object (such as a
class that extends the first class) without breaking the program. (WP LSP)
<<
Still trying to learn more, though.
Let me guess: The following hierarchy is not substitutable for you, as we
can still pass Vegetable for Fruit on foo()'s protocol. Is that correct?
class Fruit {
// intentionally left blank
}
class Vegetable extends Fruit {
// intentionally left blank
}
function foo(Fruit $fruit) {}
foo(new Vegetable); // hmmm
-- hakre