Search code examples
phpclassdrupalstaticfinal

Using a class as namespace


Are there any reasons I should not create a final class with static methods to avoid that some internal functions are called?

final class ModuleGlobalFunctions {
  static public function generateWord {
    $result = '';

    while (strlen($result) < 12) {
      $result = self::generateSyllable();
    }

    return $result
  }

  static private function generateSyllable() {
    // Generates a random syllable.
    // …
  }
}

$word = ModuleGlobalFunctions::generateWord();

// It raises an error.
$syllable = ModuleGlobalFunctions::generateSyllable();

Solution

  • Well, personally, I would recommend using classes to group similar logic. So in your case (the example you provided), it's a good idea.

    As for final, it's a toss up. I prefer to use abstract to prevent instantiation (since PHP doesn't support static classes). If you do use final, I would suggest adding a private constructor to prevent instantiation: private function __construct() {}...

    Personally, I like the concept of keeping it static. The reason is three fold. First, it's easier on memory (since there are no instances to keep track of). Second, it's faster (A static method call is faster than an instance method call). Third, and more importantly, it makes sense. Instances have a state (that's why they are instances). Does your class need a state? If so, then use an instance. If not, that's exactly what static classes are meant for...

    As for passing an instance as Sjoerd mentions, you can do that with static classes (and actually be less tightly coupled than with instances). Here's the reason. Unless you require (and check for) an interface or inheritance, you have no idea if the object actually implements the method generateWord(). But, if you pass in a callback, it doesn't matter how the method is accessed (or its underlying construction), all that matters is that it has the same (or similar) syntax (with respect to parameters and return values). Now, interfaces are a better solution to this (since it enforces the interface), but they require pretty deep understanding of OOP to get the design right. In a pinch, a callback will work quite fine for that case...