On Wed, Jan 5, 2022 at 2:17 PM David Gebler <davidgeb...@gmail.com> wrote:

> On Tue, Jan 4, 2022 at 10:35 PM Kirill Nesmeyanov <n...@xakep.ru> wrote:
>
> > How relevant do you think this idea/proposal is? And what possible
> > problems or solutions will this entail in the future?
> >
>
> I'm not convinced there's a reasonable need for it. The very nature of
> finding yourself in a situation where you want any class using a trait to
> also require other things outside the trait kind of suggests you really
> want to be using interfaces or abstract classes anyway.
>
> There is a similar concept for what I think you're trying to achieve in
> Java, though, which could also be useful in PHP if it was feasible within
> the engine - the ability to provide a default method implementation on
> interfaces themselves.
>
> Short of that, we can already effectively get there with the tools we have;
> an abstract class can use a trait and define abstract or concrete methods,
> and in doing so can implement one or more interfaces. Obviously traits can
> also declare abstract methods but I assume it's the identity/type aspect of
> an interface you want here which isn't satisfied by that approach.
>
> Also worth noting, although I can't say I'm familiar with the mechanics of
> traits in PHP's implementation, my understanding has always been that
> they're effectively compiler-level copy and paste in to a class so I'm not
> sure what interfaces are implemented by the class (or conversely allowing a
> trait to implement an interface) would be readily achievable.
>
> That's my two cents, good luck with whatever you're trying to do anyway.
>
> - David
>
>
> > --
> > Kirill Nesmeyanov
>

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.

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.

-- 
Chase Peeler
chasepee...@gmail.com

Reply via email to