Hi internals,
Given that there appears to be some appetite to reduce checks for inappropriate signatures[1] I am wondering if anyone has strong opinions — pro or con — on removing checks for static methods?
My primary use-case where I would like to see checked relaxed is for static methods used as factory methods[2].
Per [3] it seems that all but the least upvoted answer argues that LSP applies to instances, not static methods.
Per [4] it seems that all upvoted answers agree that constructors should not be constrained by LSP, and since a factory method is a form of a constructor it would seem that if constructors do not require LSP then factory methods would not either.
Does anyone see any issues with relaxing these checks for static methods that would have them downvote an RFC on the topic?
Thank you in advance.
-Mike
[1] https://wiki.php.net/rfc/inheritance_private_methods
[2] https://en.wikipedia.org/wiki/Factory_method_pattern#:~:text=The%20Factory%20Method%20design%20pattern%20is%20used%20by%20first%20defining,of%20objects%20the%20parent%20contains.
[3] https://softwareengineering.stackexchange.com/questions/101102/are-static-classes-with-static-methods-considered-solid
[4] https://stackoverflow.com/questions/5490824/should-constructors-comply-with-the-liskov-substitution-principle
Hi Mike,
wt., 16 cze 2020 o 08:59 Mike Schinkel mike@newclarity.net napisał(a):
Hi internals,
Given that there appears to be some appetite to reduce checks for
inappropriate signatures[1] I am wondering if anyone has strong opinions —
pro or con — on removing checks for static methods?My primary use-case where I would like to see checked relaxed is for
static methods used as factory methods[2].Per [3] it seems that all but the least upvoted answer argues that LSP
applies to instances, not static methods.Per [4] it seems that all upvoted answers agree that constructors should
not be constrained by LSP, and since a factory method is a form of a
constructor it would seem that if constructors do not require LSP then
factory methods would not either.Does anyone see any issues with relaxing these checks for static methods
that would have them downvote an RFC on the topic?
I can only see a one huge BC break.
What you suggest would require the deprecation of static methods on
interfaces.
Currently, you can declare a static method on an interface, like this:
interface Foo {
public static function create(): self;
}
class Bar implements Foo {
public static function create(): self { return new self(); }
}
var_dump(Bar::create());
Hence it'll be a huge BC break and the first reason downvote to the RFC I
guess.
Cheers,
Michał Marcin Brzuchalski
Hi internals,
Given that there appears to be some appetite to reduce checks for
inappropriate signatures[1] I am wondering if anyone has strong opinions —
pro or con — on removing checks for static methods?My primary use-case where I would like to see checked relaxed is for
static methods used as factory methods[2].Per [3] it seems that all but the least upvoted answer argues that LSP
applies to instances, not static methods.Per [4] it seems that all upvoted answers agree that constructors should
not be constrained by LSP, and since a factory method is a form of a
constructor it would seem that if constructors do not require LSP then
factory methods would not either.Does anyone see any issues with relaxing these checks for static methods
that would have them downvote an RFC on the topic?
Hi Mike,
The problem here is that static methods signatures are subject to LSP if
they are used in conjunction with late static binding (LSB):
class A {
public static function test() {
static::method();
// May call A::method(), B::method() or any child.
// Signature must match for this to be sensible!
}
}
class B extends A {
}
I do agree that the current situation is sub-optimal, because certainly not
all static methods actually are used with LSB. But we do not presently
distinguish these cases.
If that problem can be addressed in some way, then I agree that (non-LSB)
static methods should be exempt from LSP, just like constructors are.
Regards,
Nikita
wt., 16 cze 2020 o 09:50 Nikita Popov nikita.ppv@gmail.com napisał(a):
Hi internals,
Given that there appears to be some appetite to reduce checks for
inappropriate signatures[1] I am wondering if anyone has strong opinions
—
pro or con — on removing checks for static methods?My primary use-case where I would like to see checked relaxed is for
static methods used as factory methods[2].Per [3] it seems that all but the least upvoted answer argues that LSP
applies to instances, not static methods.Per [4] it seems that all upvoted answers agree that constructors should
not be constrained by LSP, and since a factory method is a form of a
constructor it would seem that if constructors do not require LSP then
factory methods would not either.Does anyone see any issues with relaxing these checks for static methods
that would have them downvote an RFC on the topic?Hi Mike,
The problem here is that static methods signatures are subject to LSP if
they are used in conjunction with late static binding (LSB):class A {
public static function test() {
static::method();
// May call A::method(), B::method() or any child.
// Signature must match for this to be sensible!
}
}
class B extends A {
}I do agree that the current situation is sub-optimal, because certainly not
all static methods actually are used with LSB. But we do not presently
distinguish these cases.If that problem can be addressed in some way, then I agree that (non-LSB)
static methods should be exempt from LSP, just like constructors are.
In that case maybe a core annotation like "Override" to relax checks ??
That way it'd say explicitly that it was intentional override.
Cheers,
Michał Marcin Brzuchalski
Mike Schinkel wrote:
My primary use-case where I would like to see checked relaxed is
for static methods used as factory methods[2].
Mike,
It's not reasonable to expect people to read multiple links and try
and guess what you're trying to say.
If you can't express the exact problem you're trying to address, it's
unlikely to get a useful response.
Mike Schinkel wrote:
Per [3] it seems that all but the least upvoted answer argues that LSP applies to instances,
"language-agnostic"
Arguments that apply to other languages do not necessarily map well to
PHP and how it works.
Again, the problem would need to be clearly specified before a useful
response can be given.
Michał Brzuchalski
In that case maybe a core annotation like "Override" to relax checks ??
I'm pretty sure that annotations that make it harder to reason about
how code is going to work are generally a bad idea.
cheers
Dan
Ack
Hi internals,
Given that there appears to be some appetite to reduce checks for inappropriate signatures[1] I am wondering if anyone has strong opinions — pro or con — on removing checks for static methods?
My primary use-case where I would like to see checked relaxed is for static methods used as factory methods[2].
Per [3] it seems that all but the least upvoted answer argues that LSP applies to instances, not static methods.
Per [4] it seems that all upvoted answers agree that constructors should not be constrained by LSP, and since a factory method is a form of a constructor it would seem that if constructors do not require LSP then factory methods would not either.
Does anyone see any issues with relaxing these checks for static methods that would have them downvote an RFC on the topic?
Hi Mike,
The problem here is that static methods signatures are subject to LSP if they are used in conjunction with late static binding (LSB):
class A {
public static function test() {
static::method();
// May call A::method(), B::method() or any child.
// Signature must match for this to be sensible!
}
}
class B extends A {
}I do agree that the current situation is sub-optimal, because certainly not all static methods actually are used with LSB. But we do not presently distinguish these cases.
If that problem can be addressed in some way, then I agree that (non-LSB) static methods should be exempt from LSP, just like constructors are.
Thank you for your response Nikita. Much appreciated.
Would it be reasonable to consider moving the check for incompatible signature to the first time a method is called using static::
rather than where the method is declared? That would bypass the need for a new keyword and any confusion and BC a new keyword might create.
Also, I think would assume you add need to add a flag to the child methods when they are declared so as to know if they match their parent or not?
class A {
public static function test() {
static::method(); // This would work
$b = B::create(['foo'=>'bar']); // This would work
$c = C::create(123,['foo'=>'baz']); // This would work
static::create(); // Error could be throw here?
}
}
class B extends A {
public static function method() {
}
public static function create(array $args) {
}
}
class C extends B {
public static function method() {
}
public static function create(int$id, array $args) {
}
}
-Mike