Re: Declaration of Bar::__construct() must be compatible with that of Foo::__construct()

From: Date: Thu, 26 Feb 2004 00:38:08 +0000
Subject: Re: Declaration of Bar::__construct() must be compatible with that of Foo::__construct()
References: 1 2 3 4  Groups: php.internals 
Request: Send a blank email to internals+get-8135@lists.php.net to get a copy of this message
Hello Timm, Thursday, February 26, 2004, 12:34:31 AM, you wrote: > On Wed, 2004-02-25 at 23:52, Timm Friebe wrote: >> On Wed, 2004-02-25 at 23:44, Marcus Boerger wrote: >> > Hello Timm, >> > >> > i had the same expirience today too. And also for me it makes not much >> > sense. The constructor shouldn't check inheritance rules. >> >> Neither should other methods follow this. What if I want to add a >> non-default parameter to an overriden method? > Some test cases: > 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. > ------------------------------------------------------------------- > <?php > interface Connector { > function connect($server); > } > class Foo implements Connector { > function connect($server) { } > } > class Bar extends Foo { > function connect($server, $port) { } > } ?>> > Should work #2, Bar::connect() might contain something such as Same asas above > parent::connect('foo.example.com'); > ------------------------------------------------------------------- > <?php > interface Connector { > function connect($server); > } > class Foo implements Connector { > function connect($server) { } > } > class Bar extends Foo { > function connect() { } > } ?>> > Should work #3, Bar::connect() might contain something such as Same as above. Foo::connect() can be called with any value Bar::connect() not. > parent::connect($dsn->getHost()); > ------------------------------------------------------------------- > <?php > class DSN { } > interface Connector { > function connect($server); > } > class Foo implements Connector { > function connect($server) { } > } > class Bar extends Foo { > function connect(DSN $dsn) { } > } ?>> > Should work #4, Foo::connect() adds a default argument Should work, since the calling convention from Connector is still possible in Foo and Bar. Hence Foo::connect() IS-A Connector::connect() and Bar::connect() IS-A Connector::connect(). > ------------------------------------------------------------------- > <?php > interface Connector { > function connect($server); > } > class Foo implements Connector { > function connect($server, $port= 42) { } > } > class Bar extends Foo { > function connect($server, $port= 23) { } > } ?>> > Should work #5, both interface and implementer have a default value > for the argument "server" Should work. Connector's calling convention is till valid in Bar. Hence Foo::connect() IS-A Connector::connect() and Bar::connect() IS-A Connector::connect(). > ------------------------------------------------------------------- > <?php > interface Connector { > function connect($server= 'localhost'); > } > class Foo implements Connector { > function connect($server= 'localhost') { } > } > class Bar extends Foo { > function connect($server= 'localhost', $port= 23) { } > } ?>> > Should work #6, implementation adds a default value Same as #5 only more complicated. > ------------------------------------------------------------------- > <?php > interface Connector { > function connect(); > } > class Foo implements Connector { > function connect($server= 'localhost') { } > } > class Bar extends Foo { > function connect($server= 'localhost', $port= 23) { } > } ?>> > Should NOT work #1, Foo doesn't fully implement connect() Right shouldn't work. > ------------------------------------------------------------------- > <?php > interface Connector { > function connect($server); > } > class Foo implements Connector { > function connect() { } > } > class Bar extends Foo { > function connect($server, $port) { } > } ?>> > 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. > ------------------------------------------------------------------- > <?php > class DSN { } > interface Connector { > function connect(DSN $dsn); > } > class Foo implements Connector { > function connect($dsn) { } > } > class Bar extends Foo { > function connect($dsn) { } > } ?>> > Should NOT work #3, Foo implements Connector::connect() incorrectly Should work. Still Foo::connect() IS-A Connector::connect() and Bar::connect() IS-A Connector::connect(). > ------------------------------------------------------------------- > <?php > interface Connector { > function connect($server); > } > class Foo implements Connector { > function connect($server, $port) { } > } > class Bar extends Foo { > function connect($server, $port= 23) { } > } ?>> > Should NOT work #4, Foo implements Connector::connect() incorrectly Right, shouldn't work. Inheritance doesn't apply since the signatures are incompatible. > ------------------------------------------------------------------- > <?php > interface Connector { > function connect(); > } > class Foo implements Connector { > function connect($server) { } > } > class Bar extends Foo { > function connect($server, $port) { } > } ?>> > I would simply refrain from calling > zend_do_perform_implementation_check() in inheritance. > - Timm -- Best regards, Marcus mailto:helly@php.net

« previous php.internals (#8135) next »