Skip to content
Advertisement

Make abstract class method only publicly accessible from child classes

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
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement