First off, we're talking about PHP 7.4.10, but any general intel is appreaciated!
Summarized question: I'd like to define a static method in an abstract class in such a way, that the method can only be called publicly from child classes extending the abstract class but not from the abstract class itself. Sorry if I'm being too basic here, but I literally have been searching for hours for an answer and can't even find any discussions on the topic.
Let's consider the following example (exaplantion in the comments). I want to be able to call Apple::printName()
and Pear::printName()
but not Fruit::printName()
.
abstract class Fruit
{
/*
* Oblige every child class to define a string name, nothing unusual
*/
protected abstract static function name() : string;
/*
* The problem is with the access modifier of this method here
***
* If it is public, everything is fine with Apple::printName() and Pear::printName(),
* but one can call Fruit::printName() from outside,
* resulting in PHP Error: Cannot call abstract method Fruit::name()
* this is still sort of okay, since an error will be thrown anyway,
* but I don't want the runtime to even enter the method's body
* I'd like to get an access restriction error.
***
* If it is protected, then we automatically can't call Apple::printName nor Pear::printName()
***
* So, is there a way to define the parent static method only publicly accessible from child classes without copying code?
*/
public static function printName()
{
return "My name is: " . static::name();
}
}
class Apple extends Fruit
{
protected static function name() : string
{
return "apple";
}
}
class Pear extends Fruit
{
protected static function name() : string
{
return "pear";
}
}
echo Apple::printName(); //prints "My name is: apple"
echo Pear::printName(); //prints "My name is: pear"
echo Fruit::printName(); //PHP Error: Cannot call abstract method Fruit::name() at line...
I'm also open for any alternative approaches as to how one might achieve the desired behaviour.
You can check if your instance is a subclass or not and then bail if it isnt
abstract class A1 {
public static function childrenOnly() {
return is_subclass_of(new static, 'A1');
}
}
class A2 extends A1 {
}
Al::childrenOnly(); // errors out
A2::childrenOnly(); // true