Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:79187 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 70777 invoked from network); 26 Nov 2014 10:21:36 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 26 Nov 2014 10:21:36 -0000 Authentication-Results: pb1.pair.com header.from=linepogl@gmail.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=linepogl@gmail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.214.180 as permitted sender) X-PHP-List-Original-Sender: linepogl@gmail.com X-Host-Fingerprint: 209.85.214.180 mail-ob0-f180.google.com Received: from [209.85.214.180] ([209.85.214.180:50619] helo=mail-ob0-f180.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id B1/71-56561-FA9A5745 for ; Wed, 26 Nov 2014 05:21:36 -0500 Received: by mail-ob0-f180.google.com with SMTP id wp4so1924936obc.39 for ; Wed, 26 Nov 2014 02:21:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=UoRvWPsidVKCN3PWqUfJzKBzCiySo4c7xEwjrmKd9IY=; b=vk5i2/NiGBQ9bTZutoImbPRa1hIGh7CTq5R8eyncx37zNjPlGmP+2eXO1pckFJ0ZDE mm34zJUGKPzrr6JZ5juPbCubDvEH1CzJ79a81mbDa2cIEuIBzge4VzI3OI61q373TP58 JkeCLakERSWAWKEBXOvvGw1OpZW5LTuN7UXdJ/hHhnleA0c9gqj8c+W+IUJjpEKVFAMQ VEcXCEV9sVAYwXMaqu+9/LkNa9vose9n+F+9uWZcXUkZhFvtpopF3QeKstTaPnivoiI/ jDF7IJ2S0ADBRGKedEmuONq3jUBRU8JiVv2VuGedwgnNkV/6ba0K+iGU2+F6A6ZgC9if PZig== X-Received: by 10.60.132.7 with SMTP id oq7mr18942713oeb.61.1416997292849; Wed, 26 Nov 2014 02:21:32 -0800 (PST) MIME-Version: 1.0 Received: by 10.76.160.74 with HTTP; Wed, 26 Nov 2014 02:21:12 -0800 (PST) In-Reply-To: References: <5474EF98.8070602@mabe.berlin> <5474FF0C.4010405@mabe.berlin> Date: Wed, 26 Nov 2014 11:21:12 +0100 Message-ID: To: Nikita Popov Cc: Marc Bennewitz , Levi Morrison , internals Content-Type: multipart/alternative; boundary=047d7b4722ae49be520508c064e3 Subject: Re: [PHP-DEV] [RFC][Discussion] Return Type Variance Checking From: linepogl@gmail.com (Lazare Inepologlou) --047d7b4722ae49be520508c064e3 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable 2014-11-25 23:42 GMT+01:00 Nikita Popov : > 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 ofte= n > do > >>> instantiation in base of unknown string values: > >>> > >>> class MyFactory { > >>> public static function factory($name) : AdapterInterface { > >>> $class =3D '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 a= s > > 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 sam= e > 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. > > Let's not compare these two: * Parameter types are contravariant, otherwise they are not type sound. Yet, contravariance in general is of little interest (I cannot think of any practical example), so invariance is a good compromise. * Return types are covariant. There are many useful examples already mentioned in this mailing list. http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_scienc= e)#Covariant_method_return_type Lazare INEPOLOGLOU Ing=C3=A9nieur Logiciel --047d7b4722ae49be520508c064e3--