Re: [RFC] Static classes (Was Abstract final classes)

From: Date: Mon, 01 Dec 2014 14:32:41 +0000
Subject: Re: [RFC] Static classes (Was Abstract final classes)
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-79339@lists.php.net to get a copy of this message
Hi all! > On 1 Dec 2014, at 13:58, Robert Stoll <php@tutteli.ch> wrote: > > I read your updated RFC: > https://wiki.php.net/rfc/abstract_final_class Hmm, I don’t like this new RFC either. Static classes in languages like C# exist because the language designers made the dogmatic decision to require everything to be a class. Thus, to make collections of functions, your only choice is to make a “utility class" with a bunch of static methods. To make this easier, the static keyword was added to make this easier in C# - Java doesn’t have this keyword, but it has the same pattern of static method-only classes. But PHP is not one of these dogmatic “everything must be a class” languages: it has true global functions which can be namespaced. So, why, then, does PHP need static classes? As I see it, there are two reasons: (1) Functions currently cannot be autoloaded (2) Encapsulation of state (private/protected static properties) I think both of these can be solved without perpetuating what I feel is an anti-pattern, the “utility class”. If they are solved, the need for utility classes goes away. To implement (1), someone just needs to go and finally implement function autoloading. I think Joe Watkins (krakjoe) might’ve said he’d write a patch for that, but I may be wrong. I’d certainly like to help with this effort. Implementing (2) is more difficult. We currently don’t have file-local variables like C has, we don’t even have namespaced variables. We do have static variables within functions, however. I can think of a few possible approaches to this: (1) Say that global state is evil and refuse to implement it. Some people (myself included, to an extent) would argue that global state is “spooky action at a distance” and we shouldn’t be encouraging it. In this case we encourage users to simply make normal, non-static/abstract classes and to pass an instance around. This is generally good programming practise anyway. (2) Add lexically-scoped variables, and allow normal global functions to be closures. By this I mean we add something like JavaScript’s let keyword that would make a variable that is unset when it falls out of scope (end of a {} block, end of a file etc.). Then, we allow normal functions to use the use ($var) syntax and close over variables. That’d look something like this: <?php let $x = 0; function getCounter() use(&$x) { return $x; } function incrementCounter() use(&$x) { return $x++; } // since this is the end of the file, $x falls out of scope I’d quite like this, as the introduction of lexically-scoped variables would have other advantages, too. They would make foreach() by-reference much less error-prone, for example: <?php foreach ($array as let &$item) { // do stuff with $item } // $item is unset here, since it fell out of scope when we left the {} block (3) Add file-local variables using the static keyword (à la C). That’d work something like this: <?php static $x = 0; function getCounter() { global $x; return $x; } // etc. This would work similarly to let, I suppose, it’d just only be useful for files. (4) Add namespace-local variables. No idea quite how this’d work. I’m not sure which of these is the best, though I’d leans towards (1) or (2). But I definitely feel that adding a static modifier for classes is solving the wrong problem. We don’t need to make utility classes easier to create. Rather, we need to solve the long-standing problems which force people to create utility classes in the first place. Thanks! -- Andrea Faulds http://ajf.me/

« previous php.internals (#79339) next »