Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:116829 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 67866 invoked from network); 6 Jan 2022 11:58:29 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 6 Jan 2022 11:58:29 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id ED2DF1804C4 for ; Thu, 6 Jan 2022 05:06:09 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-ua1-f53.google.com (mail-ua1-f53.google.com [209.85.222.53]) (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 ; Thu, 6 Jan 2022 05:06:09 -0800 (PST) Received: by mail-ua1-f53.google.com with SMTP id o1so4110997uap.4 for ; Thu, 06 Jan 2022 05:06:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=28w+D9S5S3rkTd2mGqveyL5b+Aobhg5V12Glja+lwIM=; b=N0GMyIsmvNwbjUuh8M7NKJtSP8cguLRq8kA4v7bZunL3EIxmX3UgEtkbRItGHaf/33 y563HKyFC0PgLpwi6pz1AoZ7xEmCMnPNMuHXqPB0HhwI8jkuHmGxiq5JIXgHToEuHSZR KKYOwvB9Vhs2ZMfxRkSTTK2Vaf9+KRPDEusW1w/LokPefoV7R9+nJ/c1V5IrChUYKJtt DFUzrqstVg9qvqfW3J3f67t9Z0Yq2oa4YyBGsRXkAXKyAAPiIQjpaKySxYpwSghmMGVq Ju+pOzICGACNLyJpBk/SpyXC298x9dyUhXkQFfg6OUfWa3loW58tcHbiP1M4Ejps4UA8 c5KQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=28w+D9S5S3rkTd2mGqveyL5b+Aobhg5V12Glja+lwIM=; b=Dmh6Q9khMhoNCcQ2keldRwdxYBoTyuGkG77iu9WX24rfduwM/9Djy9hRiwZKad9Z0F bguNs7eRqTNwxGi6mOnnYgmiaz6jejkd9PhOzAvM/IjvTG88N4n8U6O3e56c6VT7uvjr fp5sMv2jospyw19+zA81ZvLfSYmRMXzbr9l0eQD2B1VYeE12caumLMZSiU58l1FhE43R F9I/JmymOYl5phxYnB1g7RC7a+FqnA+SJRizWhILsU5mS/aoAvY8e12lXfYAYB5qV2fK IPhVDqa6wrkW0111rGzJxcs2ocYCSTVEk4DD55VFnj4PnT3+lTvYP3qfutMfDHiniDrb 8kvQ== X-Gm-Message-State: AOAM532GKL7I6pjCnyCsyU0GNiRStMdHolNrf8ZWwB7pArILormpBW3y GOVcYZDJgGzJcY8rtjAUGAJ5AU8Z1K288KTRsWY= X-Google-Smtp-Source: ABdhPJye888SGbdHwdNcm1jUU0O6GbWFzQcKfM+nZd4YazxEtdlbVEgXslcLfQsNWHXuGyrV7DKlcc1h+j/mYEEosSA= X-Received: by 2002:ab0:4868:: with SMTP id c37mr18857782uad.33.1641474368736; Thu, 06 Jan 2022 05:06:08 -0800 (PST) MIME-Version: 1.0 References: <1641335738.195767637@f174.i.mail.ru> <5a4aebf8-e592-4517-8930-d18b112ef1fd@www.fastmail.com> In-Reply-To: <5a4aebf8-e592-4517-8930-d18b112ef1fd@www.fastmail.com> Date: Thu, 6 Jan 2022 08:05:56 -0500 Message-ID: To: Larry Garfield Cc: php internals Content-Type: multipart/alternative; boundary="000000000000a8111805d4e98892" Subject: Re: [PHP-DEV] RFC: Trait expects interface From: chasepeeler@gmail.com (Chase Peeler) --000000000000a8111805d4e98892 Content-Type: text/plain; charset="UTF-8" On Wed, Jan 5, 2022 at 6:05 PM Larry Garfield wrote: > On Wed, Jan 5, 2022, at 2:35 PM, Chase Peeler wrote: > > > First, I'm someone that mainly uses traits to implement the functionality > > defined in an interface. I think that's one of the best uses for them. > > However, I'm personally not a huge fan of overly restrictive things. For > > instance, while there are definitely some use cases for them, I need a > > REALLY good reason to justify making a property/method private instead of > > protected, or making a class final. > > I am much the same. > > > As such, I think this would be better if it didn't throw a fatal error. > > When you make it optional, however, I think you are left with something > > that can be handled with an attribute just as well as a new keyword: > > #[Expects('MyInterface')] > > trait foo { } > > > > However, there might be value in generating a notice/warning, and I think > > that would require a keyword, correct? (Not that up to speed on > > annotations). Another option might be two support two new keywords: > > requires and expects. The former would throw an error if the interface > > isn't implemented while the latter will throw a warning/notice/nothing. > > > > Another option (and I haven't thought about this one enough to decide if > I > > like it) would be to have the expected interface automatically > implemented > > in the using class. This would allow the trait to be written under the > > assumption it has access to the methods defined in the interface, and > will > > then throw an error if any of the methods are not implemented in the > using > > class: > > > > interface foo { > > function a(); > > function b(); > > } > > > > trait bar expects foo { > > function c(){ > > return $this->a() + $this->b(); > > } > > } > > > > class baz { > > use foo; > > } > > > > The above would throw an error since a() and b() are never implemented > and > > baz is implementing the foo interface. You can currently get the same > > behavior if you define a() and b() as abstract in the trait. However, > this > > doesn't give you the added benefit of utilizing the interface > automatically > > within the type system. The more I think about it, the less I like this > > idea, since it doesn't require that much additional work to make the code > > clearer by explicitly implementing the interface on the class if you want > > it implemented. However, I'll go ahead and leave it here because it might > > help generate some other ideas. > > I... still don't see any use in this annotation. > > Stepping back and ignoring the syntax for a moment, there's two different > things here: > > 1. "This trait expects to be used in a class that has these other methods > on it". > 2. "This trait mostly/fully fulfills interface X, because it has methods > a, b, and c." > > For point 1, we already have that. It's called abstract methods in > traits. This is a solved problem that requires no further resolution. At > best it would be a shorthand to copying a few methods from an interface > into the trait and sticking "abstract" in front of them. I really don't > see a need for that. > > Agreed. It would also allow IDEs and what not to determine the trait has access to the interface methods that you didn't explicitly define as abstract, but I still agree that it would just be shorthand that isn't really needed. > For point 2, that's mainly useful as a way to signal to other developers > "hey, this trait has all but one method of the LoggerInterface, that's how > you'd use it", and to signal static analyzers and refactoring tools the > same thing so that they can be auto-updated if you tweak the interface. I > can see a use for point 2, and it would make my life a bit easier, but it's > overall not high priority. > > I also agree. I was focusing more on fleshing out the idea in general. I think the idea is interesting enough that it's worth discussing even if it doesn't seem like it's worth pursuing in its current form. > --Larry Garfield > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > > -- Chase Peeler chasepeeler@gmail.com --000000000000a8111805d4e98892--