On Thu, Mar 3, 2016 at 2:19 PM, Stephen Coakley <m...@stephencoakley.com>
wrote:

> On Wed, 17 Feb 2016 09:25:50 -0500, Kevin Gessner wrote:
>
> > Hello internals team!  I'd like to propose an RFC to allow traits to
> > implement interfaces.
> >
> > I've noticed s pattern in Etsy's code and elsewhere, where a trait
> > provides a common implementation of an interface.  Classes that use the
> > trait are required to also explicitly declare the interface to benefit.
> > I propose that traits be permitted to declare and implement interfaces.
> > Classes that use such a trait would then implement the interface, as
> > though it were declared on the class, without declaring the interface
> > explicitly.
> >
> > I believe this small change would be a useful improvement to the OO
> > system.  I've written a draft RFC, but I don't have karma to create the
> > wiki page for it.  Could someone please grant wiki karma to my account,
> > kevingessner?
> >
> > I don't yet have an implementation, but I'll be starting on one once
> > I've posted the RFC.  I look forward to your thoughts and feedback.
> >
> > Thanks in advance -- Kevin
> >
> > Kevin Gessner Staff Software Engineer etsy.com
>
> tl;dr: +1 and I really think that this language addition is useful and
> makes sense.
>
> Wow, I really want this feature. Reminds me of how powerful traits are in
> some other languages, such as Rust. It is very common to use traits to
> provide a common interface for something, but with some default
> implementations.
>
> Logging is a great example. Your interface might look like this (a
> familiar one, eh?):
>
> interface Logger
> {
>     public function log($level, $message, array $context = array());
>     public function error($message, array $context = array());
>     public function warning($message, array $context = array());
>     // etc...
> }
>
> where the idea is that the `error()` and such methods are a convenience
> for calling `log()` with a specific logging level. Obviously, these
> methods will be implemented in the same fashion most of the time; a trait
> would be great:
>
> trait LoggerTrait implements Logger
> {
>     abstract public function log($level, $message, array $context = array
> ());
>     public function error($message, array $context = array()) {
>         return $this->log(ERROR, $message, $context);
>     }
>     // etc...
> }
>
> With this approach, I totally agree that allowing the `LoggerTrait` to
> implement the interface makes sense; it allows implementation to be
> enforced at the trait level. The second proposal that infers the interface
> implementation when using the trait is nice too (though not completely
> mandatory). It is pretty much the same situation where you do not have to
> re-implement an interface when extending a base class that already
> implements it.
>
> --
> Stephen


The aliases issue is a little more nuanced and potentially confusing,
regardless of this interface thing:

As you can see here: https://3v4l.org/L23LJ

1. If you simply alias (use foo { bar as bat; }) then you end up with an
*additional* method with the new name, the trait method as defined is still
brought in, and _will_ override inherited methods of the same name.

2. if you try to just change the visibility, you get a fatal error (Fatal
error: Trait method bar has not been applied, because there are collisions
with other trait methods), you must create an aliased name with the new
visibility

3. Doing this (visibility + name) _only_ gives you the new method, which is
_different_ behavior to #1

If the third behaved the same as the first, then this would be a non-issue.
Unfortunately, changing this behavior would be a — particularly hard to
diagnose — BC break and therefore cannot happen IMO.

Perhaps we could look at an alternative such as:

- traits can implement interfaces, which would ensure the _trait_ adheres
to it, but _not_ automatically classes use'ing it.
- Add a new syntax: "use Trait with Interface" or "use Trait implements
Interface" or "use Trait { implements Interface; }" which *explicitly*
calls out this usage

Just some off-the-top of my head thinking as an alternative.

- Davey

Reply via email to