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
-------------------------------------------------------------------
<?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
  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
  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
-------------------------------------------------------------------
<?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"
-------------------------------------------------------------------
<?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
-------------------------------------------------------------------
<?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()
-------------------------------------------------------------------
<?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
-------------------------------------------------------------------
<?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
-------------------------------------------------------------------
<?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
-------------------------------------------------------------------
<?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
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.547
diff -u -r1.547 zend_compile.c
--- Zend/zend_compile.c	25 Feb 2004 17:23:50 -0000	1.547
+++ Zend/zend_compile.c	25 Feb 2004 23:23:42 -0000
@@ -1733,7 +1733,7 @@
 		return 0;
 	}
 
-	for (i=0; i < proto->common.num_args; i++) {
+	for (i = 0; i < proto->common.num_args; i++) {
 		if (ZEND_LOG_XOR(fe->common.arg_info[i].class_name, proto->common.arg_info[i].class_name)) {
 			/* Only one has a type hint and the other one doesn't */
 			return 0;
@@ -1828,8 +1828,11 @@
 		}
 	}
 
-	if (!zend_do_perform_implementation_check(child)) {
-		zend_error(E_COMPILE_ERROR, "Declaration of %s::%s() must be compatible with that of %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(child->common.prototype), child->common.prototype->common.function_name);
+	/* Perform implementation check when implementing an interface */
+	if (child->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE) {
+		if (!zend_do_perform_implementation_check(child)) {
+			zend_error(E_COMPILE_ERROR, "Declaration of %s::%s() must be compatible with that of %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(child->common.prototype), child->common.prototype->common.function_name);
+		}
 	}
 
 	return 0;

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

Reply via email to