On Thu, 2004-02-26 at 01:38, Marcus Boerger wrote:
> Hello Timm,
[...]
> > Should work #1, Bar::connect() adds an argument
> No the sugnature is incompatible. An instance of Foo cannot be called
> with Bar or Connector's connect() Signature. Hence Bar is not a Foo
> or Connector.

Hrm, that's quite a (huge) BC break then. I know that adding a parameter
kind-of violates the contract between Bar and Connector, but - for an
instance - omit the interface idea and think about this:

  class Error {
    function __construct($message) { }
  }

  class SQLError extends Error {
    function __construct($message, $sql) { }
  }

This gives us an error. Or, not to restrict this to constructors:

  class Printer {
    function print() { }
  }

  class MultipleFormatCapablePrinter extends Printer {
    function print($format) { }
  }

This works just fine in PHP4, where, if I call SQLError's constructor
with one argument only, I'll simply get an E_WARNING. 

You're changing this to a E_COMPILE_ERROR. Shouldn't some alarm bells
start ringing here?

With this new requirement, I'd have to make all additional parameters
optional in subclasses. This introduces more kludges:

  class MultipleFormatCapablePrinter extends Printer {
    function print($format= NULL) { 
      if (NULL === $format) {
        throw new IllegalArgumentException('Format may not be NULL');
      }
    }
  }

Now users can call this method (they could find out, e.g., via
Reflection_Method that format is an *optional* parameter - which means:
it can be ommitted, and if it is, it'll just be NULL - but it actually
can't, it's only declared with a default value because of a language
requirement) and won't even get an error if I don't catch it myself.

This doesn't come up in Java, as they have method overloading, so
MultipleFormatCapablePrinter::print() is actually a different method as
Printer::print() and you get away with it. And yes, PHP isn't Java.

[...]
> > Should NOT work #2, class / primitive clash on argument
> Wrong. Should work. Foo::connect() IS-A Connector::connect() and
> Bar::connect() IS-A Connector::connect(). It is no problem that a
> derived clsses method accepts a greater value range or set of types.

Well, this one:

> <?php
>   class DSN { }
>
>   interface Connector {
>     function connect(DSN $dsn);
>   }
>
>   class Foo implements Connector {
>     function connect($dsn) { }
>   }
>   
>   class Bar extends Foo {
>     function connect($dsn) { }
>   }
> ?>

doesn't work right now, see zend_compile.c, lines 1737 - 1744. There's
even an inline comment (!) about it there:)

Even more weirdness:

[EMAIL PROTECTED]:~/devel/php/tests > cat inheritance.php
<?php
  interface Connector {
    function connect();
  }

  class Foo implements Connector {
    function connect($server) { }
  }
?>
[EMAIL PROTECTED]:~/devel/php/tests > php-dev inheritance.php
[EMAIL PROTECTED]:~/devel/php/tests > cat inheritance-b0rked.php
<?php
  interface Connector {
    function connect($server);
  }

  class Foo implements Connector {
    function connect($server, $port) { }
  }
?>
[EMAIL PROTECTED]:~/devel/php/tests > php-dev inheritance-b0rked.php

Fatal error: Declaration of Foo::connect() must be compatible with that
of Connector::connect() in
/usr/home/thekid/devel/php/tests/inheritance-b0rked.php on line 6

Huh? So having zero arguments in the interface and one in the
implementation is OK but having one in the interface and two in the
implementation is not?

- Timm

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to