Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:56376 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 70753 invoked from network); 17 Nov 2011 22:14:10 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 17 Nov 2011 22:14:10 -0000 Authentication-Results: pb1.pair.com smtp.mail=ircmaxell@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=ircmaxell@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.215.170 as permitted sender) X-PHP-List-Original-Sender: ircmaxell@gmail.com X-Host-Fingerprint: 209.85.215.170 mail-ey0-f170.google.com Received: from [209.85.215.170] ([209.85.215.170:38618] helo=mail-ey0-f170.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 92/87-30628-13785CE4 for ; Thu, 17 Nov 2011 17:14:09 -0500 Received: by eyg7 with SMTP id 7so2697118eyg.29 for ; Thu, 17 Nov 2011 14:14:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; bh=l67/pGp3lfFjx+WASZUimF//G9KUrb7lBoJVYh6cbes=; b=xwCX+FOg/jkWDdOPhLIW0Ssc6Hlyxz+vQXd868iig9uyM7cKhpDNNrSsjmblCbeO5A /P0AjWyInzxVsOB6SRuLv3jNV0iJA15jlSbKhGIkSFQ9iLm23W4P22+8OulN4iOZqhmK wpHhnWhJaUYBoIUMiuxzunpBcl1HI5yxqIol4= MIME-Version: 1.0 Received: by 10.180.95.170 with SMTP id dl10mr460570wib.31.1321568046271; Thu, 17 Nov 2011 14:14:06 -0800 (PST) Received: by 10.216.159.142 with HTTP; Thu, 17 Nov 2011 14:14:06 -0800 (PST) In-Reply-To: <4EC578C9.4000408@ralphschindler.com> References: <4EC578C9.4000408@ralphschindler.com> Date: Thu, 17 Nov 2011 17:14:06 -0500 Message-ID: To: Ralph Schindler Cc: internals Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Subject: Re: [PHP-DEV] Changes to constructor signature checks From: ircmaxell@gmail.com (Anthony Ferrara) Honestly, I think __construct should behave like any other method when specified abstract or via an interface. I know you're thinking "But it's not an LSP violation in the constructor". But my assertion to that is that it's a violation of the contract that the abstract method / interface defined. If it's a violation of contract, I would expect to get a fatal error. After all, that's what a contract is for if not to enforce. Now, you could make the argument that it's impossible to enforce a contract (via type-hinting/instanceof) since there's no object at that point. So the contract isn't "signed". And that's the *only* reason that I could understand for wanting to change it from a fatal error to ignored. However, if that's taken, then I would expect to be notified that constructors are not enforced by the interface/abstract method. Perhaps raise a notice (or E_STRICT) in the interface on compile time that "__construct is not enforced by interfaces"... Additionally, what about other magic methods? Should they be handled separately? I could understand a contract to enforce __invoke and __toString, but what about the rest? Should they be specifiable in contract form (get/set/call/etc)? So, actually I'm not so sure on that myself. The Only use case I can think of I've used here: https://github.com/ircmaxell/PHP-CryptLib/blob/master/lib/CryptLib/Core/Abs= tractFactory.php#L51 Basically, it's an abstract factory that checks if a class name implements an interface before it will "register" the class. This is useful for implementing proxy patterns and the such. So we don't actually instantiate until later. But we want to be sure that when we do, we'll have the proper class implementing the proper interface. Since the factory will call `new` later, it needs to know the constructor is valid. So declaring the constructor in the interface actually makes sense there... So, my opinion is that either all magic methods (with the possible exception of __toString and __invoke) should be excluded from interface requirements, or none should. Either way is fine with me, but they should be consistent. And I do lean on the side that the contract is the contract, and if you change (overload) a method, you're breaking the contract. And if you specify the constructor in the contract (you don't have to), you should be bound to that contract... So I think 5.4's behavior is the proper one. I won't be upset if it changes, but if it does I think the rest of the magic methods (two mentioned withstanding) should change as well... Just my $0.02... Anthony On Thu, Nov 17, 2011 at 4:12 PM, Ralph Schindler wrote: > Hey All, > > Concerning RC1, __construct() and https://wiki.php.net/rfc/prototype_chec= ks > > I think we need to round out this discussion on the __construct() signatu= re > checking in 5.4. =A0The current behavior (RC1) feels very wrong with resp= ect > to PHP's class based, single inheritance, multiple interface, no method > overloading, allowed method-overriding nature. > > Constructors themselves, specifically in PHP, are not explicitly statical= ly > marked, but are "special" (even though they are part of the instance API, > and are callable- we'll consider this an implementation detail). =A0In > general, constructor signatures have never been (and rightfully so) gover= ned > by the LSP. =A0Why? For a few reasons: > > =A01) before calling new(), you actually don't have a subtype (yet)- the > subtype is a *product* of new() > > =A02) when you call new(), you know the exact subtype you're dealing with= . > > =A03) only subtypes who implement or override __construct() can know how = to > prepare a stateful subtype. =A0In other words, parents can't know how to > create subtypes who implement __construct() and subtypes shouldn't be > concerned with the implementation details of how a parent creates types w= hen > a subtype has overridden __construct(); > > =A04) LSP deals with behaviors and expectations of types (read: objects), > since the constructor is generally considered "static" in nature, a form = of > factory specific to the type its defined within, and since in PHP you can= 't > do (SomeClass instanceof SomeType) and since (is_a('SomeClass', 'SomeType= ') > doesn't make much sense in the context of classes), the constructor is no= t > subject to instance "behavior" rules. > > In general, developers shouldn't be putting abstract constructors inside = an > abstract class nor should they be putting constructors inside interfaces- > this is a well accepted bad practice. =A0(Neither c# or java allow this- = of > course they do have the ability to overload methods in classes for the > record. =A0In fact, static methods are not allowed either.) > > That said, we really should consider removing this limitation from > constructor signature checking. =A0Not only is it a BC break, it doesn't = make > sense in the context of PHP. > > Thoughts? > > Thanks, > Ralph Schindler > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >