vendredi 28 janvier 2022

Design pattern for declaring that class property expects a specific class or subclass

I want to declare a class property with a type that expects to be a specific class or subclass. So I need something like the following (hopefully the code is self-explanitory):

class LibraryClass
{
    private static string $utilityClass = LibraryUtilityClass::class;

    public static function setUtilityClass(string $utilityClass)
    {
        if ( is_a($utilityClass, LibraryUtilityClass::class) ) {
            self::$utilityClass = $utilityClass;
            return true;
        }
        return false;
    }
}

class MyUtilityClass extends LibraryUtilityClass{}
class FooBar{}

LibraryClass::setUtilityClass(MyUtilityClass::class); // returns true
LibraryClass::setUtilityClass(FooBar::class); //returns false (but IDE doesn't catch it)

I would really LOVE to do something more like this instead:

class LibraryClass
{
    public static [LibraryUtilityClassOrChildOf] $utilityClass = LibraryUtilityClass::class;
}
...
LibraryClass::$utilityClass = LibraryUtilityClass::class; // no issues
LibraryClass::$utilityClass = MyUtilityClass::class; // no issues
LibraryClass::$utilityClass = FooBar::class; // throws a type mismatch error (IDE will highlight)

I'd imagine this pattern is not an unusual one. I just want to extend a utility that is used by some vendor class and let LibraryClass know I'd like to use my extension instead of the default.

Does this pattern have a name, and how should it be done correctly? The first option above will work, but seems error-prone, and I'd love for my IDE to tell me it's wrong before runtime. (Maybe there's a PHPDoc way of doing this.)

I'm stuck on PHP 7.4, so no PHP 8.0 goodness for me, though a PHP8 way of doing this would certainly be nice to know.

Aucun commentaire:

Enregistrer un commentaire