Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:91494 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 94894 invoked from network); 4 Mar 2016 07:46:19 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 4 Mar 2016 07:46:19 -0000 Authentication-Results: pb1.pair.com header.from=me@daveyshafik.com; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=me@daveyshafik.com; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain daveyshafik.com from 74.125.82.47 cause and error) X-PHP-List-Original-Sender: me@daveyshafik.com X-Host-Fingerprint: 74.125.82.47 mail-wm0-f47.google.com Received: from [74.125.82.47] ([74.125.82.47:32835] helo=mail-wm0-f47.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 36/4B-08749-A8639D65 for ; Fri, 04 Mar 2016 02:17:31 -0500 Received: by mail-wm0-f47.google.com with SMTP id l68so7988957wml.0 for ; Thu, 03 Mar 2016 23:17:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daveyshafik-com.20150623.gappssmtp.com; s=20150623; h=mime-version:sender:in-reply-to:references:date:message-id:subject :from:to:cc; bh=lTf4Tk0MUBkREbP2VodYJja61i03EGki6x+yjNOWcgk=; b=YSeT+Rn2AhFAsRdTm/8HD8V22jdOU6QQoN4NjaYTqx3oBATQkjqzi5QC2oU2kyOtht t9uS9LWgyi75xtPCUCO7zSlX47kYBvuvSM+iRXXi9jtaIEUaQXt15mQcQEeQEZITxiok gz33r1sDj+FDqmjfweUFpKvmaPht6KlVTCf0BqVQx+XXs32+17QQIjT+GqQodqKgC9VU M1xMRTb3phjn9Fsza4g7Z4QowIZGBsFuLiES7Yo/kKDiZSMVf68Sa7enXNBA7w+9ZBy0 U5/SRz2Vxgxoqgmky27AAlc0HJjfXHuipmbnXxmsGLUb8DCzI8WvSrYbtWGLampl66Nw v7vw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:sender:in-reply-to:references:date :message-id:subject:from:to:cc; bh=lTf4Tk0MUBkREbP2VodYJja61i03EGki6x+yjNOWcgk=; b=JCou76uQlyFPPEAuRFHn7ugiJm2dCcx9ZHj05p84eZOAXHG1oZgfcUXtUzUKCFeJLU OET+rWtBUHvE4FHe3rMr0t3CFi8thf7CFGEcEgZF7XqGzGn50z2RNOgZcEty/tmAWux4 XfT3e2q/y8s/7+wUmMARlg15bpHcuPYwjImuYmM1USvh2xctsOgA7jQrIned8iTDkQP2 aHRffGYJ/58XPDplslBOzs/TTnRNXMIiCKN7iuFkYV71lVYvzUkz1yfeUfH/6eu/Prti ibl4sZy1OLdNB6ohPfaOB/N4uJaMIgxOEUJrNWEh9MvxdSuK8U4w3Dv2UagndFWJCzYv oGlQ== X-Gm-Message-State: AD7BkJK/Ibtt4zR1nwj/Twanp8681Sh2lr8AS5yE7kRJ6yg5S9vB6I7PKlcpvSk8+fgA1CoF4S2PqRbySieV1PlW MIME-Version: 1.0 X-Received: by 10.194.7.201 with SMTP id l9mr7299410wja.16.1457075847964; Thu, 03 Mar 2016 23:17:27 -0800 (PST) Sender: me@daveyshafik.com Received: by 10.194.138.197 with HTTP; Thu, 3 Mar 2016 23:17:27 -0800 (PST) In-Reply-To: <94.96.08749.188B8D65@pb1.pair.com> References: <94.96.08749.188B8D65@pb1.pair.com> Date: Thu, 3 Mar 2016 23:17:27 -0800 X-Google-Sender-Auth: ppW-5Eos_qgTsi-PbxJ5RxK0pFk Message-ID: To: Stephen Coakley Cc: "internals@lists.php.net" Content-Type: multipart/alternative; boundary=047d7b5d4584544904052d33e8de Subject: Re: [PHP-DEV] Re: [RFC] Traits with interfaces From: davey@php.net (Davey Shafik) --047d7b5d4584544904052d33e8de Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On Thu, Mar 3, 2016 at 2:19 PM, Stephen Coakley 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 =3D array()); > public function error($message, array $context =3D array()); > public function warning($message, array $context =3D 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 =3D arr= ay > ()); > public function error($message, array $context =3D 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 interfac= e > 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 =E2=80=94 particularly har= d to diagnose =E2=80=94 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 --047d7b5d4584544904052d33e8de--