Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:128420 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id BC8211A00BC for ; Thu, 7 Aug 2025 15:34:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1754580781; bh=9EizaJoVtTOcIgfkvvIQ3lRftSDO84mccjQQnB/SQ5c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=coyWlY45HWH8/stX0NZgP1JyCBqY8Z8QVW1peRUT+S+kWPzLis8mPzxorTmdK327K D3sCznXaNi3YBmmbvC9XhrrIbV1lNC3zKRbNC0rIuGD0jG8ZKMgzwEazdwyJAwBQ/J dXmAYAyo2GL+3+FrZy+JDjIx9C17EhdoUpoRkvBrO1oXQH6A3c9sI3i418XT8fniZh GHTCx4wYDMh9rdLO39UwIJQnl9iiTYX7Jy2adXxgX5UEh7t3PId719Q8v/tpNvakro FtgUhMzuGLyXj/yiCzCxNM506Jt7/cF7Owi57c6WHapoZo5iv4q82qOuKVn4h3SvqU ND/p+g2zDYRgQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 3D90D180048 for ; Thu, 7 Aug 2025 15:32:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-0.2 required=5.0 tests=BAYES_40,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS, SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from sonic.asd.mail.yahoo.com (sonic305-20.consmr.mail.ir2.yahoo.com [77.238.177.82]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 7 Aug 2025 15:32:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.de; s=s2048; t=1754580876; bh=vSQpXadT8eqYktdWwJVkb6AEXuUxQIxUuNOB0SnGtt0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From:Subject:Reply-To; b=A7huigNO4HEX/v8rHUsaa4vCG+szseFbREf/F9pK+l9799ad6l1PKO+LIOodp6HACXKL30Bm/d6Zf9kTWxh/yaNfZPc6SrzrdfoWGMdfGJD4fRoLbxj2V+21giAx+yv459aF1bPv3I8dH9dWS/LQevU1A3PvvRepCIyDx7kMFAXZVo9o32+6OWnmWslGBjM6n1adQ+yC6bIr/MqWfWSBhZxY5ehjwjJJIIiibbMikTorcwnt+beYI1ox6Xr/L4tk3adShahOzBxy053KZWFDOWK/OD4IenT13rygqH3Smtx3HOYRatZtDH/pyGKmAQctMCYwRD99d8C9kI8uajx6OA== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1754580876; bh=YJqO5UVFjHvxQeCnMBs0WNpa5FUpJvv+3iDE0mcCRcU=; h=X-Sonic-MF:From:To:Subject:Date:From:Subject; b=ButjMmpv8Yau8pt9kRMhNOQqt/+S7B113JUYI0/Rf5Sbgoa0sGP9tIAaZz0NKXcGNml4oJ887X0AkpLwgQ7VwAVlDuUaeOOTupmrJahJwkuJ6zsLEIpH//5EACxoQx7p9Fh2k//aBAYRHWo2jQt1YwnJle35ChzqjZExUXleHHqi8QpWmDyGGoOML0SIEp7jmUGTAUqQoWXokDxqOV77Nh1XuQvb7acfGTQLedwFkK7JOKdRo7FIgFianMLUXl8wcPp52KxkrQ3tITQ36ysfbW6baRLrani3xokERvm1IEx1/xOL+Ezk/9whVLXciFzVvVh6IT44coR2b/gdAwZ/sA== X-YMail-OSG: Or5C9xEVM1lFav1cy0o1cPqYXHW0lFnbBvtiMk4n78r9bhIN6k9PBcafCbEBK39 m2n.DdjIsUgFsZS_Dc1D8.jrsZ6ja5K2e_2OmabXnuTFTYKgyhGAu1xlwleVkm9T0SJbMUT8EKca ZzwM146anQK5BCT62wcvhTJhzUzi5RpT5lZ_K6w95FGI1Xdp2m7sCDxmizfu7vBrH2WM6xbfRyZZ yg9U.PUkzrsVq5jEiNZBVAZUI5U884tom1Xqe8kmmwikJ2KohKTVKRKOqmhayZ6DsqfcBciNAwqD WNwv6hqLU9WeUraMKmgnUa90UuM4HfI_ZtFoYBHI_I3J7QH4Rsu2eSR4wCxJtfz_mMxXpqK7dkwa TF4J2K2k39EPazQfiHuWPWzVRKxG9l5k3Lr_2LEiGOLzC.b0eEoRHb1frbqQCLXmqOajr4i.tIa0 pMz.RaQz8aJ0P4gwRbvmGmUaAvX0iTDNnv1mma3LMq3.8Q2lk_5eqPmbcpCtifXFdyhLa7OgDfUk ixS_JMPlJ4Y.ygQMLxiGvTFGnoOCdCyWFBoscQfgl8qdkroQbmst2GVCLZ9jQMfsWK0C.X6.SBxs N9FLhgmnWONh9IAydTzBw9T_pnHvl16iMm2bdyWaag.ypN4CNDlIJtMbHDdPgAO92kYtOn9xewT2 P2h8BK97vnlM13bZQkuOMZqZGeMf4DUtYmPUmcJN1LqCLyoXw8h8vXXThuDN45jQzUKR42eLIbFR eSMuM.EdUxxjKP92w8nRil9wBIbHaZWbCTr2uXq_QYvhhHyW1TY2PlagdU7E.gX.J9raq4eEcUor LbYVvV9RRAlloyR_jTb2YZ58rXhXEGoORS1LTeM1G6uE53L9gUkN5PZlaJlfihc2yBsd_Ymi8v6P R_c0p1JHBrHFc7UyvhZaKD9sa8jN3dYgkgS_dPkDzlSqVj3bS15LuqmX3i8w66wZeh00Ug8WQSeC zKDPiFmbBi1gHuqj.OkMgX.cAAuA_1kmsEtX7PKc4_LCB7f_LiYc4OSs8LXPjCu9QL9SX63vp6QB DAwXtn31v5GXsgEeVunYQV4DB776QaAjtB3lg9Tx1oW7UI7bbBca8zwZ48PPRZQ3mDgVvjaZMs4T _MU5NxyI7gcn_7QhQ0uhcfIufoMcStjV0ksA5.6oinm3K9tu73JrG2GhuXeF3uyzDJgDijcbznBg eGtq7ffBHeJ1eEUYHGKMQ4pHoysbge66ZDm0.DiGey_uxNCcJJDf0jxBVAv62C8.hQQ8moqWpAQv HU9VK9tY1BkHgKyGmV46BwXkzWH96VBYxxuBITsEoWku8J8EsKhPKwBbxT161WUywLovfs4FiIMf VUrA7XLlbnVtfyLqcc68Yo1kT4MwBalqvvEBAuOZ1CoFXJU4syhoVcREjwBqGFXE9v2xoDesIngI n22eIu1GVKumEBHmApzUytz4Nldei2qEupk8iggM.Ukzn7blgan1w8H9EnaBPOeS7TDwRIRMZnDi 68ycIxXodXZyObenxAS2rEOwyeDiqQx905IQ_0j7ohCP.xjsuZ2sdeoi9TWR1.P4TkTWfCrLDzDh wx5XXa0q7Q6_Jv35q_nvszi6vr852L8RgOl86JOJ_MmVgfnCx5DbyuQNCxDi10TADkqZSP3BIE3l HGk.b69NELJUBnDtum_DlCDOA5.VkNHj_L3t3KB6EosxvXwWQ3uVrfIDFuPzGEj5UYLYRTOx5l1B AK2S5Gxp3ZwBe70bO76dodhg6_47t8B2QJQOel_GV5tlSy9YKTqIS4yWNIw4zdOba.fHc4xmlDYR kfBWtz3LGz4iYO458l_GHtj.1IJpS5RjCPGtv51Xw5G1hrh.OyUpyQ5Uq7saPQukHMie1LkNOFPO 7M97MxRfGscW3AeHSCb9FSEPRhl4EM.bkN1Vw6uhVgoZRwyuoLwkam_qGXsiR_wS52dHMPtNy58p Jm8ORG8ViHzFK2qtLg_3bCsz1d3ZHpwVMRYVUs1bkvlV_tG2AohIfO5wyOFE3NUwrERSn1mRmzGk tBwa2R7M9ITgehZoNQ22ok6LBGmjroaG015QpL1n_q1pjaODblXVtSuuh93TKEo929JsBsxUCkQ3 mjWlU7EgR4f2_3XO8c7U85sTiXq.yZpMGGe2r1f7fZdpDjC43OQGOhLz1brydDjtFlRyzBUQhYrA nIz8_K375vgZNnqbafnXOpLUV_S2PdwRubr6H5uCm5EtfAX1x1FLlrkhMGhtsKPm.VNkZjdxV9LD HbzI2Nbr5toQdmG8lG6u53MR8PoJtkDU3jRVJv1leQtLSMGStKxxsyyJXjrl6AAcyNQ-- X-Sonic-MF: X-Sonic-ID: 0a08dd90-ba83-42b8-9654-b460aabee1e9 Received: from sonic.gate.mail.ne1.yahoo.com by sonic305.consmr.mail.ir2.yahoo.com with HTTP; Thu, 7 Aug 2025 15:34:36 +0000 Received: by hermes--production-ir2-858bd4ff7b-g5qbj (Yahoo Inc. Hermes SMTP Server) with ESMTPA ID d2d02ba637159f2b82595c1610f08265; Thu, 07 Aug 2025 15:34:31 +0000 (UTC) Content-Type: text/plain; charset=utf-8 Message-ID: <1754572388117.3270901082.2211913261@yahoo.de> To: rob@bottled.codes Cc: internals@lists.php.net Subject: Re: [PHP-DEV] Protected inheritance hierarchies Date: Thu, 07 Aug 2025 15:34:30 +0000 In-Reply-To: References: X-Mailer: Vivaldi Mail User-Agent: Vivaldi Mail/7.5.3735.58 Content-Transfer-Encoding: quoted-printable Precedence: list list-help: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 From: hanskrentel@yahoo.de (Hans Krentel) On Thursday 07 August 2025 08:46:26 (+02:00), Rob Landers wrote: >=20 >=20 > On Thu, Aug 7, 2025, at 00:38, Hans Krentel wrote: > >=20 > >=20 > >=20 > > On Wednesday 06 August 2025 13:41:14 (+02:00), Rob Landers wrote: > >=20 > > >=20 > > >=20 > > > On Wed, Aug 6, 2025, at 13:26, Hans Krentel wrote: > > > >=20 > > > >=20 > > > >=20 > > > > On Sunday 03 August 2025 11:30:13 (+02:00), Rob Landers wrote: > > > >=20 > > > > > I'm not sure that this is a bug. You can redeclare the same type = and=20 > > add=20 > > > > hooks (or change them), which breaks all assumptions about=20 > > > > substitutability. > > > >=20 > > > > Rob, maybe you can lecture me a bit: Isn't substitutability on = the=20 > > public=20 > > > > interface / protocol only? What am I not seeing in your example? > > >=20 > > > From a child class's perspective, the "public interface" is both=20 > > protected + public of the parent. If you change or misuse a = parent's=20 > > implementation or invariants, it violates LSP, even if it doesn't = affect=20 > > external clients immediately. > >=20 > > Ah okay, that part is not in my book, this explains to me why in = your=20 > > example it violates substitutability for you, and with that thinking = it=20 > > also prevents or degrades implementability for me so to say, as = otherwise I=20 > > could not make use of visibility in classes - it would take away that = tool=20 > > from me or I would not treat it well, potentially leading to defects in= the=20 > > program. >=20 > See my reply to Jonathan. But you are free to dismiss LSP when needed. = There are a lot of times when LSP isn=E2=80=99t the right design constraint= (which I briefly mention in that email), for example, during larger = migration/refactors, specialized proxies, caching results, etc., or even = using sibling classes as friend classes. >=20 > PHP doesn=E2=80=99t strictly enforce LSP everywhere. It will get out of = your way when you need it to. It=E2=80=99s your code, you can do whatever = you want with it.=20 >=20 > Even when I see an LSP violation at work (rare, but it happens), I = don=E2=80=99t point it out as such, but instead point out why the approach = is a bad idea (maintainability, principle of least surprise, etc). If they = do it continuously, then I might have to invest in some coaching for the = dev, but mostly, people don=E2=80=99t violate LSP for the more obvious = reasons, and when they do, they usually have good reasons (see above). Thanks a lot for sharing your thoughts that openly and briefly, much = appreceated. This all sounds rather sane to me, given PHP is not a design by contract = language and what makes LSP stand out from formal type theory can get = easily lost then, especially when applied with force. I've also studied your other reply to Jonathan. >=20 > >=20 > > > > > > Take for example: > > >=20 > > > class Fruit { > > > public string $kind { get =3D> "fruit" } > > > } > > >=20 > > > class Vegetable extends Fruit { > > > public string $kind { get =3D> "vegetable" } > > > } > > >=20 > > > function foo(Fruit $fruit) {} > > >=20 > > > foo(new Vegetable); // hmmm > > >=20 > > > This is a "soft" violation that only makes sense to us humans, but = PHP=20 > > allows it. It requires us humans to realize we are performing an = LSP=20 > > violation and refactor the code so that we don't pass a Carrot to = someone=20 > > expecting a Mango. > >=20 > > Thankfully in this example it is all public, but I definitely would = say=20 > > this is not an LSP violation, just saying. > >=20 > > > > > > This can be done through protected means as well (simply replace = the=20 > > properties above as protected properties used internally), and it won't= be=20 > > as obvious to consumers outside the class, but still there, nonetheless= . > > >=20 > >=20 > > Okay, this is it probably just like above (for me): When $kind would = be=20 > > protected, it would not be part of the public protocol, and the=20 > > substitutability test with the PHP runtime would still pass for the=20 > > foo(Fruit) event with a Vegetable that is a Fruit (extends). That would= be=20 > > a test for substitutability, per the PHP runtime guarantees (it = returns=20 > > successfully after sending the message), it does not break the = program: > >=20 > > >> an object (such as a class) may be replaced by a sub-object (such as= a=20 > > class that extends the first class) without breaking the program. (WP = LSP)=20 > > << > >=20 > > Still trying to learn more, though. > >=20 > > Let me guess: The following hierarchy is not substitutable for you, as = we=20 > > can still pass Vegetable for Fruit on foo()'s protocol. Is that correct= ? > >=20 > >=20 > > class Fruit { > > // intentionally left blank > > } > >=20 > > class Vegetable extends Fruit { > > // intentionally left blank > > } > >=20 > > function foo(Fruit $fruit) {} > >=20 > > foo(new Vegetable); // hmmm > >=20 > >=20 > > -- hakre >=20 > I don=E2=80=99t see any reason why this example would violate LSP. There = is no discernible difference between the two classes. LSP only says they = are substituable in regards to type, and behaviour, and an empty class is = probably only a sentinel value, in which case the behaviour is external to = the type. I might have an issue with saying a vegetable is a fruit, but = that is a naming issue=E2=80=A6 and naming is hard.=20 So by protocol, this settled a bit more in harmony. Fine. And while naming is hard, names are harder: Given that LSP, PHP and the = (earlier with hooks) class definitions are all human made, and furthermore = that fruits and vegetables grow from nature, there is or was at least one = local jurisdiction that would have needed them in their program exactly = that way: a vegetable declared Fruit. A delicious example of sub-typing = refreshingly POLArizing. Thanks Rob. -- hakre