Static classes in PHP via abstract keyword?

后端 未结 10 1949
孤独总比滥情好
孤独总比滥情好 2021-01-31 19:00

According to the PHP manual, a class like this:

abstract class Example {}

cannot be instantiated. If I need a class without instance, e.g. for

相关标签:
10条回答
  • 2021-01-31 19:31

    There are patterns in OO that are common and well-recognized. Using abstract in an unconventional way may cause confusion (sorry, my some examples are in Java instead of PHP):

    • abstract class - a class meant to conceptualize a common ancestor, but of which actual instances are not meant to exist (e.g. shape is an abstract superclass for rectangle and triangle).
      Commonly implemented by:
      • use abstract modifier on class to prevent direct instantiation, but allow deriving from the class
    • utility class - a class that does not represent an object in the solution space, but rather is a collection of useful static operations/methods, e.g. Math class in Java.
      Commonly implemented by:
      • make class non-derivable, e.g. Java uses the final modifier on class, and
      • prevent direct instantiation - provide no constructors and hide or disable any implicit or default constructors (and copy constructors)
    • singleton class - a class that does represent an object in the solution space, but whose instantiation is controlled or limited, often to insure there is only one instance.
      Commonly implemented by:
      • make class non-derivable, e.g. Java uses the final modifier on class, and
      • prevent direct instantiation - provide no constructors and hide or disable any implicit or default constructors (and copy constructors), and
      • provide a specific means to acquire an instance - a static method (often getInstance()) that returns the only instance or one of the limited number of instances
    0 讨论(0)
  • 2021-01-31 19:35

    abstract really is meant to indicate a "blueprint", as you call it, for class inheritance.

    Registries generally follow a singleton pattern, which means they it would instantiate itself in a private variable. Defining it as abstract would prevent this from working.

    0 讨论(0)
  • 2021-01-31 19:36

    As other guys said, you cannot instantiate an abstract class. You could use static methods in your class to prevent instantiating, but I'm not really a fan of doing so unless I have a proper reason.

    I might be little bit off-topic now, but in your example you said you wanted this for Registry pattern class. What is the reason you don't want to instantiate it? Wouldn't it better to create an instance of Registry for each registry you want to use?

    Something like:

    class Registry {
        private $_objects = array( );
    
        public function set( $name, $object ) {
            $this->_objects[ $name ] = $object;
        }
    
        public function get( $name ) {
            return $this->_objects[ $name ];
        }
    }
    

    I wouldn't even use Singleton in this case.

    0 讨论(0)
  • 2021-01-31 19:36

    The purpose of an abstract class is to define methods that are 1) meaningful to other classes and 2) not meaningful when not in the context of one of those classes.

    To paraphase some of the php docs, imagine you are connecting to a database. Connecting to a database doesn't make much sense unless you have a particular kind of database to connect to. Yet connecting is something you will want to do regardless of the kind of database. Therefore, connecting can be defined in an abstract database class and inherited, and made meaningful by, say, a MYSQL class.

    From your requirements, it sounds like you don't intend to do this but instead simply require a class without an instance. Whilst you could use an abstract class to enforce this behaviour, this seems hacky to me because it abuses the purpose of abstract classes. If I encounter an abstract class, I should be able to reasonably expect that this will have some abstract methods, for example, but your class will have none.

    Therefore, a singleton seems like a better option.

    However, if the reason you wish to have a class without an instance is simply so that you can call it anywhere then why do you even have a class at all? Why not just load every variable as a global and then you can just call it directly rather than through the class?

    I think the best way to do this is to instantiate the class and then pass it around with dependency injection. If you are too lazy to do that (and fair enough if you are! Its your code, not mine.) then don't bother with the class at all.

    UPDATE: It seems like you are conflicted between 2 needs: The need to do things quickly and the need to do things the right way. If you don't care about carrying a ton of global variables for the sake of saving yourself time, you will assumedly prefer using abstract over a singleton because it involves less typing. Pick which need is more important to you and stick with it.

    The right way here is definitely not to use a Singleton or an abstract class and instead use dependency injection. The fast way is to have a ton of globals or an abstract class.

    0 讨论(0)
  • 2021-01-31 19:39

    Setting a class to abstract that only defines static properties/methods won't have a real effect. You can extend the class, instantiate it, and call a method on it and it would change the static class properties. Obviously very confusing.

    Abstract is also misleading. Abstract is ment to define an class that implements some functionality, but needs more behaviour (added via inheritance) to function properly. On top of that it's usually a feature that shouldn't be used with static at all. You are practically inviting programmers to use it wrong.

    Short answer: A private constructor would be more expressive and fail safe.

    0 讨论(0)
  • 2021-01-31 19:45

    If your class is not meant to define some super-type, it should not be declared as abstract, I'd say.

    In your case, I would rather go with a class :

    • That defines __construct and __clone as private methods
      • so the class cannot be instanciated from outside
    • And, this way, your class could create an instance of itself
      • See the Singleton design pattern, about that, btw


    Now, why use a Singleton, and not only static methods ? I suppose that, at least a couple of reasons can be valid :

    • Using a singleton means using an instance of the class ; makes it easier to transform a non-singleton class to a singleton one : only have to make __construct and __clone private, and add some getInstance method.
    • Using a singleton also means you have access to everything you can use with a normal instance : $this, properties, ...
    • Oh, a third one (not sure about that, but might have its importance) : with PHP < 5.3, you have less possibilities with static methods/data :
      • __callStatic has only been introduced in PHP 5.3
      • There is no __getStatic, __setStatic, ...
      • Same for a couple of other Magic methods !
    • Late Static Binding has only been added with PHP 5.3 ; and not having it often makes it harder, when working with static methods/classes ; especially when using inheritance.


    This being said, yes, some code like this :

    abstract class MyClass {
        protected static $data;
        public static function setA($a) {
            self::$data['a'] = $a;
        }
        public static function getA() {
            return self::$data['a'];
        }
    }
    
    MyClass::setA(20);
    var_dump(MyClass::getA());
    

    Will work... But it doesn't feel quite natural... and this is a very simple example (see what I said earlier with Late Static Binding, and magic methods).

    0 讨论(0)
提交回复
热议问题