On Feb 26, 2004, at 1:49 AM, Andi Gutmans wrote:


You are breaking the isA relationship. We fixed this so that from now on, people will not make such mistakes anymore (I think it's the right way to go, so that we don't leave broken functionality around).
You can enable compatibility mode to make this work or specify a default value (as you saw) for $bar so that you are keeping the interface of the base class.

First Interfaces. Interfaces are a purely a type checking construct. There is nothing you can do with interfaces in PHP 5 that you can't already do with classes in PHP 4 except type checking. So, it makes sense that implementing an interface obligates you to some method signature type checking. Implementing an interface means this class supports this contract.


interface BaseInterface1 {
        function example($value = NULL);
}

class DefaultArguments1 implements BaseInterface1 {
        function example($value = NULL);
}

The class implements the interface contract. This should work.



interface BaseInterface2 {
        function example($value);
}

class DefaultArguments2 implements BaseInterface {
        function example($value = NULL);
}

The class implements the interface contract. This should work.



interface BaseInterface3 {
        function example();
}

class VariableArguments1 implements BaseInterface3 {
        function example() {
                if (func_num_args() <= 1) {
                ...
                }
        }
}

The class and interface signatures match, but the class has an implementation twist in that it accepts a variable number of arguments. This should work. The interface doesn't specify whether () means no arguments or variable number of arguments, so one has to assume variable number.


interface BaseInterface1 { function example($value = NULL); }

class VariableArguments2 implements BaseInterface1 {

        function example() {
                if (func_num_args() <= 1) {
                ...
                }
        }
}

This class may implement the contract, too. Its just hard to tell from the declarations. Traditionally in PHP, declarations have not meant much. Since interfaces are new, whether or not this works is optional. if not, then perhaps a varargs keyword will be added in a later version to help match the declarations.


Now constructors and interfaces...


interface BaseInterface4 {
        function __construct();
}

What does it mean to "construct" an interface? Nothing. This should be a compile time error.

Now old style constructors

interface BaseInterface4 {
        function OldConstructor1();
}

class OldConstructor1 implements BaseInterface4 {
}

This is an error, too. The name of a method in the interface cannot match the name of a class that implements it (or match the name of any of the parent classes.) This protects the classes constructors from becoming involved in an interface.

There is nothing wrong with the interface by iteself. There is nothing wrong with the class by itself. They just cannot be used together.

Moving on the the class side...

Constructors aren't are really an object method, they are a class method. As such, their signatures should not be a part of any normal method signature checks. Here is an example:

class Shape {
        function __construct() {}
}

class Polygon {
        function  __construct($sides) { parent::_construct(); }
}

class Rectangle {
function __construct($sides, $length, $width) { parent::_construct($sides); }
}


class Square {
function __construct($sides, $size) { parent::_construct($sides, $size, $size) }
}


Here each class maintains the is_a relationship with its predecessor. However, the constructors are essentially unrelated except where explicitly linked in the code. The signatures are not linked by the declaration. This is correct. PHP should NOT compare the signatures of the construction methods. This is consistent with other languages and consistent with the idea that constructors are class methods, not instance methods. This capability is essential.

Actually, unless I am mistaken, constructors ARE just instance methods in PHP with a fancy naming convention.

Now moving on to the signatures of non-construction methods.

PHP implements a dynamic message passing object paradigm (ala small talk) instead of a static type based object paradigm (ala java). This is a good thing. The message (method name) is passed up the inheritance tree until an object says "I can do that." Only then to the arguments get bound and the method implementation on the object invoked. The checking against number of arguments occurs at binding time. This is not bad. nor is it incorrect.

PHP will never know what types are being passed, so it simulates overloading with default arguments and variable argument functions.

On Feb 26, 2004, at 1:51 AM, Andi Gutmans wrote:

Regular inheritance has to follow the same isA rules as interfaces. Inheritance is exactly the same thing except that it also has code and private/protected methods/members whereas interfaces don't.

regular inheritance does not have to follow the same rules. interfaces are an optional type checking device. Classes can get along just fine with out the type checking.


PHP is fundamentally a weakly typed dynamically typed language. A language that lets you do things like $a = "23" + "5". has no business enforcing method signature relationships in class inheritance. It hasn't before and shouldn't now.

The message passing paradigm is not wrong. Type conformance is not the one true way. Type checking should be strictly optional in PHP, with no type checking being the default.

You understand completely. It is incorrect to override methods w/ incompatible signature. We don't check this in compatibility mode.

If anything, it is the type checking that should go into the configuration option ghetto.


On Feb 25, 2004, at 5:52 PM, Timm Friebe wrote:

zend_do_perform_implementation_check() is called from
do_inherit_method_check() (both in zend_compile.c) which in turn is
called for inheritance *and* for interfaces. The behaviour is fully
desirable when implementing interfaces but not for regular inheritance.

I agree.


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



Reply via email to