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