Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:51001 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 49880 invoked from network); 10 Dec 2010 21:00:23 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 10 Dec 2010 21:00:23 -0000 Authentication-Results: pb1.pair.com header.from=quickshiftin@gmail.com; sender-id=pass; domainkeys=bad Authentication-Results: pb1.pair.com smtp.mail=quickshiftin@gmail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.214.45 as permitted sender) DomainKey-Status: bad X-DomainKeys: Ecelerity dk_validate implementing draft-delany-domainkeys-base-01 X-PHP-List-Original-Sender: quickshiftin@gmail.com X-Host-Fingerprint: 209.85.214.45 mail-bw0-f45.google.com Received: from [209.85.214.45] ([209.85.214.45:45129] helo=mail-bw0-f45.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id D5/51-39602-5E4920D4 for ; Fri, 10 Dec 2010 16:00:22 -0500 Received: by bwz16 with SMTP id 16so4764369bwz.32 for ; Fri, 10 Dec 2010 13:00:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:in-reply-to :references:date:message-id:subject:from:to:cc:content-type; bh=zr0kxP8zyjL0IeEUY3fazO389bRawxEhynzlNwUbzIE=; b=RnAxmZuFUhZB7lRPxuHpPlUDW7pksJdL8SiePojVkV7Oz+MZqUS/kfF75ESU2Pn1Cw 0OtRkpvBMpx91WvnbjC935OmMvliR1cOiGEV3sb99xaH24JJ/oBfbeNTxkEUUv/VKij8 PAjImgL2OYvgQ3p3OMLxxQ1I44YgA/6gyLmwc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; b=JJcwYuBoVylaR3ZedM7WKstDtHgX4MUTUQJHQjqoKdddg7bC+SyymPSw7Lqr5uJJ/a GucSj3v138qHZ9OghmX4+vnGef0wv2T8ACYfjfPyZmQKys2akNzTMGI294g3Mr3hlKFs Pqenp5FyA5qCe5Za/Zl95AYLmiIo3cxsb4x5Y= MIME-Version: 1.0 Received: by 10.204.48.86 with SMTP id q22mr1213302bkf.141.1292014814875; Fri, 10 Dec 2010 13:00:14 -0800 (PST) Received: by 10.204.112.208 with HTTP; Fri, 10 Dec 2010 13:00:14 -0800 (PST) In-Reply-To: References: <9CD87200-33CB-40BE-A81C-36FD7471F59C@stefan-marr.de> <9A31F2F9-ED6B-4BE5-A6E2-EB4536E8667F@stefan-marr.de> Date: Fri, 10 Dec 2010 14:00:14 -0700 Message-ID: To: Chad Fulton Cc: internals@lists.php.net Content-Type: multipart/alternative; boundary=0016e6d7e10115cfb8049714a4d0 Subject: Re: [PHP-DEV] Traits expecting interfaces implicitly leads to expensive runtime checks From: quickshiftin@gmail.com (Nathan Nobbe) --0016e6d7e10115cfb8049714a4d0 Content-Type: text/plain; charset=UTF-8 On Fri, Dec 10, 2010 at 12:39 PM, Chad Fulton wrote: > On Fri, Dec 10, 2010 at 10:39 AM, Nathan Nobbe > wrote: > > On Fri, Dec 10, 2010 at 11:04 AM, Chad Fulton > wrote: > >> > >> On Fri, Dec 10, 2010 at 9:29 AM, Nathan Nobbe > >> wrote: > >> > On Fri, Dec 10, 2010 at 10:15 AM, Martin Wernstahl > >> > wrote: > >> > > >> >> First i have to say that I am not a PHP internals developer, but as a > >> >> user > >> >> I think it would maybe be better to just let the trait use the > >> >> implements > >> >> keyword, and "copy" that to the classes utilizing the trait? > >> >> > >> > > >> > This is actually in the RFC as a rejected proposal > >> > > >> > http://wiki.php.net/rfc/traits#rejected_features > >> > > >> > But what I'm talking about is something different. We're not trying > to > >> > say > >> > 'these are the methods implemented in the trait', rather, 'this trait > >> > expects a class it is used with to be of a certain type or implement a > >> > certain interface' for the trait to do its job. > >> > > >> > -nathan > >> > > >> > >> Shouldn't the burden be on the programmer to make sure the trait works > >> with the class using it rather than on the compiler? If they try to > >> use a trait that requires methods that don't exist, it will error out > >> anyway, so it won't be difficult to debug. > > > > Well I know PHP is a dynamic language but what about all the compile time > > features that have come along over the years. The abstract keyword for > > example vs. the PHP4 way of implementing an 'abstract' method which was > > triggering an error in the default implementation in a base class. > > One of the main things a lot of PHP programmers I've worked with hate is > > waiting for code to hit production and encountering a runtime error w/ > > something that could have been caught at compile time. I know the notion > of > > compile time in a scripting language like PHP is much less removed from > that > > of C++, Java etc, however there is a notion of it there, obviously. > > Also, I would suggest this feature be optional, so there is no need to > use > > it if you don't like it. But for those of us who would like to defer as > > much type checking to the compiler as possible so we don't need runtime > > checks all over our code or prayers that we've tested every line before > > production, it would certainly be nice. > > Lastly, you may know that traits will allow PHP programmers to move away > > from the delegate pattern which is a common workaround to multiple > > inheritance at this point. However, in speaking with a colleague over > the > > concept I'm proposing yesterday we discovered the delegate model actually > > does allow you to specify which class/interface the delegate is used w/, > it > > would be sad not to see comparable support in the trait feature which > will > > mostly eliminate the need for the delegate pattern, see my quick example. > > > class MainClass { > > private $_oDelegate = null; > > function addDelegate() { > > $this->_oDelegate = new Delegate($this); > > } > > } > > class Delegate { > > private function $_oMain = null; > > /// delegate gets to say what it can be used with via type hinting > > function __construct(MainClass $oMainClass) > > { > > $this->_oMain = $oMainClass; > > } > > } > > ?> > > Imagine how much cleaner this could be w/ traits, yet just as expressive > > > class MainClass { > > use Delegate; > > } > > trait Delegate require MainClass { > > ... > > } > > ?> > > -nathan > > > > As a note, I'm not strongly opposed to this proposal, since I don't > think it would do any harm. It just seems to me like a "kitchen sink" > feature. > > The issue for me is that traits, as I understand them, are there > primarily for horizontal code re-use via compile-time "copy/paste". > With that in mind, I feel like the developer is responsible for making > sure the methods they copy into their classes make sense, just as they > would have to do if they physically copied and pasted them. > Copy & paste itself leads to duplicated unmaintainable code, so traits are introduced (among other reasons) to prohibit this practice. Why not take it a step further and let a trait definition be as expressive as possible, eliminating ambiguity, right out of the gate? > I think your example above isn't quite what you meant to show, since > you're requiring a specific class and not an interface (since PHP only > allows one class definition for a class name, you're not gaining > anything via traits, since the trait could only be used for that > specific class, in which case why not just have the code in the class > in the first place?). > In retrospect Chad, that's a good point, and perhaps there is no reason to allow marking of classes as required by traits. > If we take your example in a more general case using interfaces, I > still can't see what the benefit is. All it does is provide a more > explicit and immediate error message for developers (e.g. instead of > "method not found" error when the bad method call is made at runtime, > you get a "classes using trait must implement " at > compile time). > Exactly, catch it at compile time rather than runtime, that's all it is really, just like the benefit of discovering a given subclass doesn't implement a given abstract method so that I don't go any further and run code guaranteed not to work. > Again, I'm not against it, but maybe be too much hand holding, since > the developer should make sure using the trait makes sense first? > Couldn't the same be said for a developer extending an abstract class, or implementing an interface? And also, a developer is to look through the entire definition of a trait to know which methods it's going to depend on? I know abstract is there as Stefan showed, but as we've both observed that approach can get messy quickly. -nathan --0016e6d7e10115cfb8049714a4d0--