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