Allow "static" type

php.internals

Marc Bennewitz

9 years ago
Hi all, I would like to know your opinion about using "static" as type-hint similar to "self" and how simple / complex it would be to implement. Example - using static: https://3v4l.org/XqDma class Base { public static function test(static $obj) : static { echo get_class($obj) . "\n"; return new static($obj); } } class Ext extends Base {} $base = new Base; $ext = new Ext; Base::test($base); Base::test($ext); Ext::test($ext); Ext::test($base); Example - using self: https://3v4l.org/Tp7k6 - Boilerplate code to check if the given argument is an instance of static - No way for IDEs to test Ext::test returning an instance of Ext class Base { public static function test(self $obj) : self { echo get_class($obj) . "\n"; if (!$obj instanceof static) { throw new InvalidArgumentException(sprintf( "Object (%s) must be an instance of %s", get_class($obj), static::class )); } return new static($obj); } } class Ext extends Base {} $base = new Base; $ext = new Ext; Base::test($base); Base::test($ext); Ext::test($ext); Ext::test($base); Thanks Marc

Net Mo

9 years ago
Hi​, static could be definitely a valid return type, but I don't see this happening for parameters, for the same reasons this is disallowed: class A{ function bar(A $a){} } class B extends A{ function bar(B $b){} } // must be contravariant, but B is covariant to A However again, it works as return type: class A{ function bar(): A{} } class B extends A{ function bar(): B{} } // must be covariant, and B is covariant to A

Giovanni Giacobbi

9 years ago
On 28 January 2017 at 10:18, Wes <netmo.php@gmail.com> wrote:
> Hi​, static could be definitely a valid return type, but I don't see this > happening for parameters, for the same reasons this is disallowed: > > class A{ function bar(A $a){} } > class B extends A{ function bar(B $b){} } // must be contravariant, but B > is covariant to A > >
That's not completely true, the contravariance rule exists to defend the polymorphism and overriding, BUT this is a static scope so it is *almost* like an overloading, I.E. B will have *another* method bar which is different from A's, the only difference is that B should also inherit original's A::bar but it does not, it's like A::bar(A) is not inherited. Before anyone say it, I know you can use the $a::bar() syntax to invoke static methods, but I consider that a shorthand of A::bar() and what people should *always* use unless they have complete control over the code and invocation stacks. I did in fact hit a use for this feature a long time ago where I wanted to have a static method which is able to operate (in my case delete from database) an instance of an object, and I solved it WAY before the introduction of all this syntactic madness I've been witnessing recently, which is: public static function delete(self $object) { $class = get_called_class(); $baseclass = get_class($object); assert('($class == $baseclass) || is_subclass_of($class, $baseclass)'); // do whatever you need to do } The reason is that I always want the caller to be aware of what he is doing and never use the "standard" method on a subclass which actually redefines it. Even though I like the proposal and I would personally use it, I'm against it because I think PHP has been getting a lot of "features" which only safe a few keystrokes in very edge cases but complicate the language and steep the learning curve, which was the only real strong point of PHP, its simplicity. I think the latter thought is a bit offtopic, one day I will start a thread to start philosophizing on the direction PHP had taken the past years (good old times when the strict type hinting was rejected because it made it too complicated for newcomers, lol). Cheers
-- Giovanni Giacobbi

Net Mo

9 years ago
I completely agree with what you said. Static inheritance is wrong. Static members shouldn't be inherited. This is what I think and probably what you think too. But it's too late to fix this. I don't think it's worth changing the expectations of the users, which rely on inherited members to be compatible with those in super types.