If you shouldn't be able to instantiate a class then it should be abstract
and define its methods as static
. However, somebody could just subclass the class and make it non-abstract. If you don't want that to be a possibility either then the class should be abstract final
.
If you do this, you can call methods directly on the class in question with ClassName::methodName()
syntax. Do bear in mind that classes written like this can't make use of $this
because it is only valid for an object instance. If you need the class to maintain state then you will have to define a static variable and use it with self::
or static::
syntax.
abstract final class SomeClass
{
private static $var = "";
public static function setVar($newVal)
{
self::$var = (string) $newVal;
}
public static function getVar()
{
return self::$var;
}
}
A word of caution on doing this though, use of abstract classes/methods can very easily lead to tightly coupled code which is bad for a number of reasons.
For example, if you write a class that calls the methods of an abstract class directly by any means other than inheriting from the abstract class, then it will be impossible to unit test that class in isolation. It will always require your abstract class to be part of the test suite too, which means it's more difficult to determine whether a test failure has been caused by a fault in the class under test or in the abstract class it's depending on.
What's more, if the abstract class you're depending on serves as an accessor for a data source, then you also will not be able to mock the class during tests. Mocking is a very powerful way of verifying the correctness of a class without having to rely on the environment that the class is running in. for example, you can mock a database access class with a compatible object that always returns the same data from an array instead of hitting an actual database. This means that you can guarantee that when you run a test it will run with data in a state that you have full control over. If you access a database via an abstract class's methods then you can't replace that for testing and suddenly you may end up with a test suite that might succeed or fail depending on the state of the database at the time you run the test. Even worse, if your tests involve writing to the database then you could potentially corrupt your data source when running tests.