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
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
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
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.