>>  do you know any reason for this?
>>
>
> The reason for this is simply that B must act like A since every B object is
> also an object of A.
>
>

The reason for restricting the method signature in the Subclass is to
guarantee that an instance of a Subclass should work where an instance
of the Superclass is expected.
I think that this can be achieved with much weaker rules than
expecting that the method in the Subclass has the exact signature as
the Superclass.
For example we do allow overriding visibility, but only weakening
it(eg. private->protected or protected->public is allowed but
public->protected isn't), else there could be cases where using the
instance of the Superclass works, but the Subclass won't.
Another thing that we should take into account: php is no java, so we
don't have to require exactly matching method signature, as in php the
method name cannot be ambiguous(we don't support declaring methods
with the same name but different argument signature), and because of
this passing more arguments than it was declared also supported in the
userland functions/methods.

So based on this, the following cases are which would make a Subclass
incompatible with it's Superclass:
- tightening visibility (we already restrict this)
- declaring more arguments in the Subclass than in the Superclass, and
having no default value for those.
- declaring different typehints in the Subclass than it was declared
in the Superclass. theoretically we could also allow changing the
typehinting where it makes sense (for example it would be safe to
allow changing the typehint from Foo to Bar if Bar extends/implements
Foo), but I think that would require too much work, so I'm fine with
requiring the same typehint if it was present in the parent.
- removing default values from the arguments. (declaring the same
argument as in the Superclass, but without default value, while the
Superclass declared it with default value)

the following cases would be allowed to change the method signature
without making the Subclass incompatible with it's Superclass:
- the Subclass could declare fewer arguments than it's Superclass.
this could sound wrong, but as I mentioned, the engine allows passing
more arguments, than it was declared, so Subclass would work
everywhere where the Superclass is expected, and the arguments can be
accessed through func_get_args. of course it would allow someone to
shot himself in the foot(if he chose not to fetch the arguments from
the method body), but that can happen already(for example. the
Subclass can return different type than what the Superclass would, or
it could throw different Exceptions, or just return some bogus value,
etc.).
- the Subclass could declare more argument than it's Superclass, as
long, as the additional argument are having default values.
- the Subclass could declare arguments without typehints which were
declared with typehints in the Superclass.
- the Subclass could declare arguments with default values which were
declared without default values in the Superclass.

for example:

class super{
  public function init(array $a=null){

  }
}

could be extended like:

// one additional argument, but it has default value, so it is fine
class sub extends super{
  public function init(array $a=null, $b=false){

  }
}

// same argument but without the typehint
class sub extends super{
  public function init($a=null){

  }
}

// fewer arguments
class sub extends super{
  public function init(){

  }
}

// remove the typehint
class sub extends super{
  public function init($a=null){

  }
}

but the followings are all invalid:

// invalid, because it removes the default value
class sub extends super{
  public function init(array $a){

  }
}

// invalid, because the additional argument doesn't have a default value
class sub extends super{
  public function init(array $a, $b){

  }
}

// invalid, because changes the typehint
class sub extends super{
  public function init(StdClass $a, $b){

  }
}

ps: the invalid signature should generate catchable fatal error, not
fatal error imo, we are using fatal error many places where it would
be reasonable to use Catchable fatal error, as Fatals should be only
used where the Engine is left in an unstable state, or which cannot be
recovered from.

-- 
Ferenc Kovács
@Tyr43l - http://tyrael.hu

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

Reply via email to