Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:79184 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 34688 invoked from network); 25 Nov 2014 22:42:43 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 25 Nov 2014 22:42:43 -0000 Authentication-Results: pb1.pair.com smtp.mail=nikita.ppv@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=nikita.ppv@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.212.179 as permitted sender) X-PHP-List-Original-Sender: nikita.ppv@gmail.com X-Host-Fingerprint: 209.85.212.179 mail-wi0-f179.google.com Received: from [209.85.212.179] ([209.85.212.179:41487] helo=mail-wi0-f179.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id B9/6F-40624-2E505745 for ; Tue, 25 Nov 2014 17:42:43 -0500 Received: by mail-wi0-f179.google.com with SMTP id ex7so3084550wid.6 for ; Tue, 25 Nov 2014 14:42:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=ovVyFEC2uq6ew5w0UfR8aU7nW7Tdxvv5FR2gkEAKpQ4=; b=pyYZUshKgWofL23/tJGdzVVMn8ll4YmRSpKy3rFD/rLPQayF1GRmEzdXYHC6moZn4H PXejHPjng4gUDtBvUffUCdl/OFsT6CfQ/ou23keJbOtkMJ/j3b1pAUmUd5LQQWUAu6Nt aliyJOF/Ybvi89V7u86tbLtJdKkG+Hnemv3gO4ot2JEgSyktscgfWK0KPSSn6u00w9gn +e6UxoVWFgATAxgNVeG1WogCWacCXdDIDHv2SWsvXasyjYMwpAstAEVhxGNyJrJb1cOQ r+4NlCnLjBoLR1T5QuFYKYg56dWBh+VovVgCqgt+gsD9A/kWK6yhrIPRZ8vrkuIra31R 9XSQ== MIME-Version: 1.0 X-Received: by 10.181.13.106 with SMTP id ex10mr35779857wid.36.1416955358319; Tue, 25 Nov 2014 14:42:38 -0800 (PST) Received: by 10.27.10.4 with HTTP; Tue, 25 Nov 2014 14:42:38 -0800 (PST) In-Reply-To: <5474FF0C.4010405@mabe.berlin> References: <5474EF98.8070602@mabe.berlin> <5474FF0C.4010405@mabe.berlin> Date: Tue, 25 Nov 2014 23:42:38 +0100 Message-ID: To: Marc Bennewitz Cc: Levi Morrison , internals Content-Type: multipart/alternative; boundary=f46d043be12ccb9a6f0508b6a068 Subject: Re: [PHP-DEV] [RFC][Discussion] Return Type Variance Checking From: nikita.ppv@gmail.com (Nikita Popov) --f46d043be12ccb9a6f0508b6a068 Content-Type: text/plain; charset=UTF-8 On Tue, Nov 25, 2014 at 11:13 PM, Marc Bennewitz wrote: > > Am 25.11.2014 um 22:43 schrieb Levi Morrison: > > On Tue, Nov 25, 2014 at 2:07 PM, Marc Bennewitz wrote: >> >>> I think it's required to do the type check on runtime (Option 2) because >>> one of the use cases for return type-hint are factories and such often do >>> instantiation in base of unknown string values: >>> >>> class MyFactory { >>> public static function factory($name) : AdapterInterface { >>> $class = 'MyNamespace\Adapter\' . $name; >>> return $class(); >>> } >>> } >>> >> It seems that I did not explain this clearly enough; I apologize. The >> variance has to do with the declared type in the function signature >> when inheritance is involved, not the type of the value returned by >> the function. >> >> For instance, under any of the three options this code will work just >> fine: >> >> class Foo {} >> class Goo extends Foo {} >> >> class FooFactory { >> function create(): Foo { return new Goo(); } >> } >> >> As long as the return value from FooFactory::create returns Foo or a >> subtype of Foo (such as Goo), then it will work. >> >> The variance that is under discussion in this thread is about the >> declared return type in the signature: >> >> class GooFactory extends FooFactory { >> function create(): Goo {} >> } >> >> In this case, GooFactory::create() declares a return type of Goo, >> which is a subtype of Foo [the return type of the inherited method >> FooFactory::create()]. This is a covariant return type. >> >> If we choose option 3, the only possible return type for >> GooFactory::create is Foo. >> >> Hopefully this clarifies the issue. >> > Yes it does - thank you for explanation - my mistake :/ > > Option 3 is a no go not from OOP perspective and from consistency pov as > we already allow this in type-hint: > > class FooFactory { > function create(Foo $foo): Foo { return $foo; } > } > > class GooFactory extends FooFactory { > function create(Goo $goo): Goo { return $goo; } > > } > This is not correct. Parameter typehints in PHP are invariant, so you are not allowed to change them during inheritance. However LSP violations during inheritance of *non-abstract* methods currently uses a very low error level (E_STRICT), so you probably didn't notice. If you try the same thing with an interface method or an explicitly abstract method, you will receive a fatal error: interface I1 { function foo(A $a); } class C1 implements I1 { function foo(B $b) { ... } } This code snippet will result in a fatal error, because it violates type invariance. Nikita --f46d043be12ccb9a6f0508b6a068--