FAQ
Hi,

Probly rehashing an old conversation here, but I'm wondering why the
following isn't supported

<?php
abstract class AbstractServer {}
class ConcreteServer extends AbstractServer {}

abstract class AbstractClient {
abstract function doStuff(AbstractServer $o);
}

class ConcreteClient extends AbstractClient {
function doStuff(ConcreteServer $o) {}
}
?>

This results in a fatal
Fatal error: Declaration of ConcreteClient::doStuff() must be compatible
with that of AbstractClient::doStuff() in
/Users/quickshiftin/gitRepos/timberline/php-api-v15-client/testOverride.php
on line 11

I was reading a few posts from way back when

http://marc.info/?t=107774904800001&r=1&w=2

yet still find myself wondering. I think it can be said here that if
there's a contract defined by AbstractClient::doStuff, that same contract is
honored by ConcreteClient::doStuff. I also think changing the language to
support this notion wouldn't raise BC issues for the most part (at all?)
since at the moment you're forced to move to the lowest common denominator
in the tree, in this case

class ConcreteClient extends AbstractClient {
function doStuff(AbstractServer $o) {}
}

your feedback appreciated,

-nathan

Search Discussions

  • Ferenc Kovacs at Oct 7, 2010 at 7:25 am

    On Thu, Oct 7, 2010 at 7:56 AM, Nathan Nobbe wrote:

    Hi,

    Probly rehashing an old conversation here, but I'm wondering why the
    following isn't supported

    <?php
    abstract class AbstractServer {}
    class ConcreteServer extends AbstractServer {}

    abstract class AbstractClient {
    abstract function doStuff(AbstractServer $o);
    }

    class ConcreteClient extends AbstractClient {
    function doStuff(ConcreteServer $o) {}
    }
    ?>

    This results in a fatal
    Fatal error: Declaration of ConcreteClient::doStuff() must be compatible
    with that of AbstractClient::doStuff() in
    /Users/quickshiftin/gitRepos/timberline/php-api-v15-client/testOverride.php
    on line 11

    I was reading a few posts from way back when

    http://marc.info/?t=107774904800001&r=1&w=2

    yet still find myself wondering. I think it can be said here that if
    there's a contract defined by AbstractClient::doStuff, that same contract
    is
    honored by ConcreteClient::doStuff. I also think changing the language to
    support this notion wouldn't raise BC issues for the most part (at all?)
    since at the moment you're forced to move to the lowest common denominator
    in the tree, in this case

    class ConcreteClient extends AbstractClient {
    function doStuff(AbstractServer $o) {}
    }

    your feedback appreciated,

    -nathan

    It was discussed recently:

    http://marc.info/?l=php-internals&m=128220433328115&w=2

    Tyrael
  • Ionut G. Stan at Oct 7, 2010 at 8:03 am

    On 07/Oct/10 8:56 AM, Nathan Nobbe wrote:
    Hi,

    Probly rehashing an old conversation here, but I'm wondering why the
    following isn't supported

    <?php
    abstract class AbstractServer {}
    class ConcreteServer extends AbstractServer {}

    abstract class AbstractClient {
    abstract function doStuff(AbstractServer $o);
    }

    class ConcreteClient extends AbstractClient {
    function doStuff(ConcreteServer $o) {}
    }
    ?>
    Here's the problem:

    class ConcreteServer2 extends AbstractServer
    {}

    Now, ConcreteClient can't receive an instance of ConcreteServer2 as an
    argument, although the initial hint, AbstractServer would have allowed it.

    --
    Ionuț G. Stan | http://igstan.ro
  • Richard Lynch at Oct 8, 2010 at 2:07 am

    On Thu, October 7, 2010 12:56 am, Nathan Nobbe wrote:
    <?php
    abstract class AbstractServer {}
    class ConcreteServer extends AbstractServer {}

    abstract class AbstractClient {
    abstract function doStuff(AbstractServer $o);
    }

    class ConcreteClient extends AbstractClient {
    function doStuff(ConcreteServer $o) {}
    }
    ?>

    This results in a fatal
    Fatal error: Declaration of ConcreteClient::doStuff() must be
    compatible
    with that of AbstractClient::doStuff() in
    /Users/quickshiftin/gitRepos/timberline/php-api-v15-client/testOverride.php
    on line 11

    I was reading a few posts from way back when

    http://marc.info/?t=107774904800001&r=1&w=2

    yet still find myself wondering. I think it can be said here that if
    there's a contract defined by AbstractClient::doStuff, that same
    contract is
    honored by ConcreteClient::doStuff. I also think changing the
    language to
    support this notion wouldn't raise BC issues for the most part (at
    all?)
    since at the moment you're forced to move to the lowest common
    denominator
    in the tree, in this case

    class ConcreteClient extends AbstractClient {
    function doStuff(AbstractServer $o) {}
    }

    your feedback appreciated,
    I can see why you think it "should" work, but have you considered all
    the possible combinations of children/parent abstract/concrete
    classes, and what happens when you do:

    class QuickMixClient extends ConcreteClient {
    function doStuff(AbstractServer $o) {}
    }

    class QuickMixServer extends AbstractServer {
    }

    $quickie = new QuickMixServer;
    $client = new QuickMixCilent;
    $client->doStuff($quickie);

    Kosher? Or not?

    It's kosher for the QuickMix doStuff, but does not satisfy the
    ConcreteServer requirement of ConcreteClient.

    So does PHP need to examine every method on every class, and then
    complain at compile time?...

    That sounds painful to me...
    .
    .
    .

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupphp-internals @
categoriesphp
postedOct 7, '10 at 5:56a
activeOct 8, '10 at 2:07a
posts4
users4
websitephp.net

People

Translate

site design / logo © 2023 Grokbase