Re: [RFC] Static classes (Was Abstract final classes)
| From: | Andrea Faulds | 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/