Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:114174 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 76269 invoked from network); 25 Apr 2021 23:29:37 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 25 Apr 2021 23:29:37 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 3390F1804CC for ; Sun, 25 Apr 2021 16:33:29 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-qk1-f176.google.com (mail-qk1-f176.google.com [209.85.222.176]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sun, 25 Apr 2021 16:33:28 -0700 (PDT) Received: by mail-qk1-f176.google.com with SMTP id i12so23411817qke.3 for ; Sun, 25 Apr 2021 16:33:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=newclarity-net.20150623.gappssmtp.com; s=20150623; h=mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=f+vQzqKzKKGmf8Hai35v6y/MjMEkB5f9FNe4w77ap5g=; b=KrcrY8Tev0+JHhUpC0sLg2K87N5ppBQg6ur4zgssrVWCVJxomAyMecZZFk75DVvqEm bB2lA55F27bRtubAFIcADIovla9xuRNZ9PTWRYAbF5Px6T82OioE3DIhK32sgpf9jX2W R3EySuILdMP6+v/zKbNHNz37yBnC2dPkn8WWa2m7nG7IZNGQbIuIYLQraVBB/9+XfLaw i9VckosGK1lFrV6jobDeJ1ul/yCHPMnyFmtD3EIYQA3vX77LA4ZKyHsMfHJzcMxTCS1q GNjPltUUN6WOjbz6DZ0IqHjx1vl4Mcpq2+KNORc3NqhXeDYS6SMdespthfe2WaqCkX1g 893w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:subject:from:in-reply-to:date:cc :content-transfer-encoding:message-id:references:to; bh=f+vQzqKzKKGmf8Hai35v6y/MjMEkB5f9FNe4w77ap5g=; b=SNk0FZGnxlkB1iJ7AbYoPYzfz13AtUcoGcW5m9g4nnfNsMMbbh20VBVyEpH8NcyoVc xQQ6smggenNMvQpOJO3LfyTLSqk6PN/4aEF9orfN0Sap+GsqnFkp6BF9R2PjcdGZfhKY OQQbroyWLelLqMsHu6XVlduCQ2lxKyp9oYxy1ZP8CgTJ68pJf1L+pppso8LzRwr4brjJ asSqEVsu1vPEchkO+M6eaKR+HsVl1n4zjubKjgy3kbBbXU0noVp0oYptZpnMowalGIFP CS3Kw0B4v5VvL9qprxVw3tMu90UZ7m76m8It/FoDF5YdVolUAYEV+UxzKBddwY6NJuP1 1kNg== X-Gm-Message-State: AOAM533jy4cKiBX6Xy1PAWMfOUKZ4wNh0x40OVjxvzsDkbRAPRJD9Ubb fPiqwXILtcCVEon7bI2Mklbieg== X-Google-Smtp-Source: ABdhPJy8CGBQ5b0NjjYElHmNxpQr/zYERjtygypZWb+RM/u9QCPDgqQ3Tlrdq+4nhP0amDGLHLY+eQ== X-Received: by 2002:a37:bb42:: with SMTP id l63mr14962220qkf.127.1619393605478; Sun, 25 Apr 2021 16:33:25 -0700 (PDT) Received: from [192.168.1.10] (c-24-98-254-8.hsd1.ga.comcast.net. [24.98.254.8]) by smtp.gmail.com with ESMTPSA id d3sm9469737qtm.56.2021.04.25.16.33.23 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 25 Apr 2021 16:33:24 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.120.23.2.4\)) In-Reply-To: Date: Sun, 25 Apr 2021 19:33:22 -0400 Cc: PHP internals Content-Transfer-Encoding: quoted-printable Message-ID: <6B61C61B-5E32-4059-B9F9-DB9F6B93648B@newclarity.net> References: <5b9f1500-615a-48f1-815f-1d48b327ef90@processus.org> <179049b1475.11134368b213512.254739612773841999@void.tn> <0BF84585-DDC3-4B25-BFD2-D8B916D135EE@newclarity.net> To: David Gebler X-Mailer: Apple Mail (2.3608.120.23.2.4) Subject: Re: [PHP-DEV] [RFC][Draft] Sealed Classes From: mike@newclarity.net (Mike Schinkel) I did not expect nor intend to go down the rabbit hole regarding this = topic, so this will likely be my last reply on this thread. > On Apr 25, 2021, at 4:51 PM, David Gebler = wrote: >=20 > On Sun, Apr 25, 2021 at 8:52 PM Mike Schinkel = wrote: >=20 >>> On Apr 25, 2021, at 1:52 PM, David Gebler = wrote: >>>=20 >>> Still, all these problems are solved to the same degree if you add a >>> #[Sealed] attribute to a class which has no functional impact. You = have >>> sufficiently indicated to any user that extending this class is not = a >>> designed feature and may cause backwards-incompatible breaks with = future >>> releases - in a way that both a programmer and IDE can reason about, >> which >>> in PHP's context is what matters. Attributes arguably even have a = greater >>> qualitative advantage that they can be applied right down as far as >>> individual method parameters. >>=20 >> In my experience, if a developer needs access to a feature that is = easily >> available via the use of a method that is merely documented as = internal-use >> only, the developer will use it rather anyway than spend a lot more = time >> trying to work around what that method makes easily available. = Especially >> if that documented internal-use only is about not subclassing. >>=20 >> And if many other developers do that, the original developer will = still >> have the same problem as if they didn't document it as internal-use = only. >>=20 >> But I do acknowledge your experience might be different. FWIW. >>=20 >=20 > You're answering a different point to the one I'm making, which is = that in > contrast to a language like Java, where the compiler gets a benefit = out of > reasoning about virtual vs non-virtual methods, the use of sealed as a > language construct in an interpreted language like PHP can do nothing = which > isn't already achieved by annotation - the expression of intent. Assuming the annotation is only advisory and the keyword is actionable = then of course PHP can do something not already achieved by annotation; = it can throw an error when it comes across a class that attempts to = extend a sealed class that has not named it as an exception. =20 >=20 >>> In Java the idea of final and sealed classes makes more sense, since = we >>> actually to some extent need the compiler to be able to reason about >> these >>> types and can gain optimization and code generation benefits from = its >> being >>> able to do so. PHP's concept of typing and implementation of type >> checking >>> as an interpreted language is completely different. >>>=20 >>> I wonder, if final and sealed as language constructs really offer = the >>> guarantees about intent and safety their advocates say they do, why = are >>> they not the default? Why can no one point me to a language where I = have >> to >>> write something like >>>=20 >>> extendable class Foo permits all { .... } >>>=20 >>> (and there are people who would be in favour of making = inheritability >> this >>> explicit, but I'm not one of them) >>=20 >> Well, I can't point you to a language that works that way because I = don't >> know more than a handful of languages in depth =E2=80=94 although = there may be one >> =E2=80=94 but I can point you to a language that does not even allow = you to >> subclass: Go. >>=20 >> The Go designers wanted to get away from the fragile base class = problem so >> they provided embedding instead: >>=20 >>=20 >> = https://medium.com/@simplyianm/why-gos-structs-are-superior-to-class-based= -inheritance-b661ba897c67 >>=20 >> I program more in Go now than in PHP, and I can confirm that its = approach >> works brilliantly. Better IMO than what PHP currently offers in that >> respect. >>=20 >=20 > Again, this doesn't seem relevant to the discussion in respect of PHP = or > the RFC we're talking about. I don't have a Go background but I'm = learning > it at the moment and I like it a lot. Nonetheless it's neither = comparable > to PHP nor object oriented in a conventional sense so any direct = comparison > here is probably not too useful. If you are going to equivocate and add more limiting criteria to your = claim post hoc then of course the example I provided won't be too = useful. >>> It's one thing as an author of code to say "I only intended and = support >>> this finite set of use-cases", it's quite another to say "and you = should >> be >>> impeded from proceeding with any legitimate use-case I didn't = imagine or >>> foresee" >>=20 >> I do respect that as a user of other developer's code you might view = it >> that way. >>=20 >> But then I also can respect the library or framework developer who = chooses >> to make their own job less difficult by (wanting to) mark a class to = be >> sealed. >>=20 >> You claim "it's quite another thing to say" but I don't think a = developer >> of library or framework code should be required to offer features to = their >> users they do not want to offer. It is the developer's prerogative; = if >> they want to be able to mark their classes as sealed they should be >> empowered to do so. IMHO, anyway. >>=20 >=20 > My argument is not that there aren't legitimate cases where you want = to > indicate a class or interface as sealed, nor that developers should = not be > empowered to make this indication. It is that in PHP, as an = interpreted > language, there is little to no benefit in expressing this through a = new > language construct than through existing constructs and design = patterns. I'll just leave this as-is since Larry and Saif have already explained = how there is in-fact benefit for `sealed` in PHP. >>=20 >>> In practice, the only thing I've ever seen this achieve is to create >>> difficulties, while the claimed benefits can be adequately (and = better) >>> achieved through existing patterns like annotations, interfaces and = DI. >>=20 >> I would argue that maybe the reason you have only seen it create >> difficulties is because of your own perspective and experiences that = are, >> by definition, anecdotal and thus limited. >>=20 >> OTOH Fabien Potencier and/or Taylor Otwell might have a different >> experiences and thus a different perspective on what those benefits = are >> (but I am admittedly just hypothesizing here.) >>=20 >=20 > Allow me to re-phrase then, in a way which removes anecdotes from the > equation; what is the problem in PHP which would be solved by adding = the > sealed keyword (or any equivalent) and can't be solved via attributes = or > other features already part of the language? There's no runtime = benefit and > an IDE can read attributes to tell you you're breaking someone else's > intentions and prevent you making a mistake in respect of that. As I said above, there is indeed a runtime benefit. PHP can throw an = error and disallow extending sealed classes that do not have stated = permission. > Part of the argument I see for these features in languages which have = them > is that inheritance is dangerous. I do not see it as "dangerous" though you are certainly free to view it = that way. Having `sealed` would allow developer to significantly reduce the number = of scenarios where they would need to bump major version numbers because = of breaking changes since, in reality, any newly added method to an = existing extensible class is potentially a breaking change. Not having `sealed` is not so much "dangerous" as it increases the = likelihood that a new release should be classified as a breaking change = and thus requires everyone who uses the release to consider whether or = not the new release will break their code. Even if a developer has never = extended any of the 3rd party classes they will still need to spend time = to understand what has changes and ponder whether if effects their code = or not. > And it certainly can be, but it can also > be dangerous to put in new language features which can be = misunderstood and > used inappropriately. I just think we need to carefully weigh up the > cost/benefit of new language features (particularly new syntax). I think weighing the cost/benefit is exactly what this discussions are = doing. -Mike=