Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:99186 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 45969 invoked from network); 25 May 2017 20:02:47 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 25 May 2017 20:02:47 -0000 Authentication-Results: pb1.pair.com smtp.mail=danack@basereality.com; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=danack@basereality.com; sender-id=unknown Received-SPF: error (pb1.pair.com: domain basereality.com from 209.85.192.171 cause and error) X-PHP-List-Original-Sender: danack@basereality.com X-Host-Fingerprint: 209.85.192.171 mail-pf0-f171.google.com Received: from [209.85.192.171] ([209.85.192.171:35175] helo=mail-pf0-f171.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 98/8D-10292-66837295 for ; Thu, 25 May 2017 16:02:47 -0400 Received: by mail-pf0-f171.google.com with SMTP id n23so176582524pfb.2 for ; Thu, 25 May 2017 13:02:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=basereality-com.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=IaNNf3uwssU9nhCnaku2/AFVdFCNJIVkdQmXAmh1gQk=; b=AmhOcO96QPvoor5ro8/7U4ZpkLgtbzPgQ8KE99mxcrvdfBzfaUrD+I0wtjSk7+TtuE 7Sw8eMXJFb4fkuC33SAZ6madnSUtfEQ5jYseVjmhHinwa5tcA5UpTZpOc1JRnsQvtOb/ NcR1tiFn171DDmqTyFO6XXFLqiXICD+NhOtOahKzFSVLn1TBs/OfnTdvglYxeX+gZHtc xNcAGKqnCADiIiUbFzCYPAfWdWNztIiXefN22n3NV05l/1gf5WzoJ787LYQ60kPi0+eY l9gM1h7SwjmiEOhR7GPzYucZDglbtnqGiO6H5wza7wBOI+h97vpch53xhyg1ue1myiFm ToEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=IaNNf3uwssU9nhCnaku2/AFVdFCNJIVkdQmXAmh1gQk=; b=cGBKWgNxd40BbiMX+iOJkLpdwI4rrklQ9x2XcNc/4mPkKDHtVs7YbWWida7dlXX13T ZfmQmR3BB2pKey1y/DPMYonV5gmc4dDhOAb2pnRSglmRQkcapLO97B1T0s4YjXIQBwmH hirtf3+RXE9jOiPBwSIGcsmlU6mZmLsyM9ggbJmXL7w24oRokGltnL9R+MTYU8jSd+92 2mDh9G34cZHxzFJIp4LSDV79d+R792NzBR/Vd+JLN99Y+bzPandHMZRpy8Q9eC9Ygtmb z0T/iEIdsDAtG9BNrcGUHHA3j51Qp5CU0RJSaliy5OY8ZdXA+8V9hj2W9/JQFZdxSpLQ 7scQ== X-Gm-Message-State: AODbwcCX7qecAfPa+oqFb6F+mYe5VxFCQb7RWoh5txuitvnNYCAJ4N4x fwlJX3BQEumbjO2HbapMPKboXcGFrdxXO0ioWw== X-Received: by 10.98.219.130 with SMTP id f124mr46491687pfg.171.1495742563722; Thu, 25 May 2017 13:02:43 -0700 (PDT) MIME-Version: 1.0 Received: by 10.100.151.163 with HTTP; Thu, 25 May 2017 13:02:43 -0700 (PDT) X-Originating-IP: [77.99.17.151] In-Reply-To: References: <269187f4-5924-a7cc-9163-40134546451f@fleshgrinder.com> Date: Thu, 25 May 2017 21:02:43 +0100 Message-ID: To: Andrey Andreev Cc: "internals@lists.php.net" , Rasmus Schultz Content-Type: text/plain; charset="UTF-8" Subject: Re: [PHP-DEV] Parameter type widening RFC From: danack@basereality.com (Dan Ackroyd) Andrey Andreev wrote: > When I said I don't claim to fully understand LSP Hi Andrey, The RFC specifically didn't mention LSP....because that is separate from co/contravariance. It's unfortunate for other people to be throwing the two around at you with a lack of precision. (disclaimer - I helped Niklas draft the RFC, but I still muddle up the terms occassionaly also.) > What I don't understand is how do we get from this...To this: It's not difficult, just subtle. First, some code, to define some classes: interface A { function foo(Bar $bar); } class B implements A { function foo($bar) { // this function is capable of handling either objects // of type Bar, or strings } } There are two separate things here. First - method B::foo is contravariant to method A::foo, which just means that anything that can be successfully passed as the parameter to A::foo can also be passed to B::foo. Second - because of the contravariance, and because PHP allows classes to implement interfaces, the Liskov substition principle kicks in, and we can substitute an object of type B anywhere where an object of type A is expected. e.g. If we have a function that takes A as a parameter: function doSomething(A $a) { $a->foo(new Bar()); } Both of these are guaranteed* to be work equivalently due to LSP: doSomething(new A()); doSomething(new B()); > by the above logic, that it considers "mixed" a subtype of ... everything? No, I think you've been confused by people saying LSP where they meant contravariance. Although class B can accept either an object of type Bar, or a string that doesn't meant that a string is a sub-type of Bar. Instead because B obeys the contravariance rules for the implementation of the method, an object of type B can be substituted where A is expected. Incidentally, this would be a lot nicer if we had passed the union type RFC, and so were able to write: class B implements A { function foo(Bar|string $bar) { // hurrah for static code inspection. } } Or for avoiding 'clashing' interfaces: interface C { function foo(Bar $bar); } interface D { function foo(string $bar); } class E implements C, D { function foo(Bar|string $bar) { //This method satifies the contracts for both interfaces. } } > Every (re)definition and example talks about > substituting *objects* with their subtypes It is a little unfortunate that a lot of information about type systems is presented in object-oriented languages, as the same thing applies to things that aren't objects, e.g. arrays, generators => iterable and also callback functions e.g. the callable passed to set_exception_handler() must accept at least \Exception in PHP 5.6 and \Throwable in PHP 7, but it's fine for it to accept a wider set of parameters. cheers Dan *guarantees about program behaviour with LSP are kind of...bogus. In fact it's probably better to concentrate on how it usually makes your program be easier to write, rather than relying too heavily on it for an application to actually 'behave' correctly in all scenarios.