From:             nairbv at yahoo dot com
Operating system: 
PHP version:      6CVS-2009-05-14 (CVS)
PHP Bug Type:     Feature/Change Request
Bug description:  need a way to do type safe enumerations in php

Description:
------------
**This is a feature request, not a bug

I can find no reasonable way of implementing any kind of useful typesafe
enumeration pattern in php without an additional language feature.  There
are a number of potential language features that could fix this.  Here are
a couple of examples.

1) a "final" keyword for static class members, and permitting static
initialisation at class load time.  Final is *not* the same thing as
"const."  "final" + load-time initialisers would allow code like this:

final class color {
    private $name;
    public static final $RED = new boolean('Red');
    public static final $ORANGE = new boolean('Orange');
    //.....
    function __construct($name){ $this->name=$name; }
    function __toString() { return $this->name; }
}

without static, you can't initialise them in the class.  Without final,
any user of your class can color::RED = color::ORANGE (maybe accidentally
in an if statement) and you're class is hosed.  With const, they can only
be primitives, which can't have any functionality or attributes.  Finals
would be initialised at run time (sometimes even in constructors etc, as
long as they are only initialised once).

Don't confuse what I said about static initialisers with "late static
binding," an already planned feature un-related to this request.

2) or, including an actual enum class would be nice.  see:
http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html for an
example.

3) ideally we'd have both.  Having an enum class is obviously better than
my first suggestion for the specific problem of implementing enums, but the
features in my first suggestion also have other applications.

I'm seeing a lot of code that in various ways attempts to work around this
lack.  None of them are elegant, in that they all involve repetitive, hard
to read, or unsafe code.

one example I came across recently looked like this:
final class foo {
    static $foo;
    static $bar;

    function __construct()
    {
        $foo = new someotherclass('attribute1','attribute2');
        $bar = new someotherclass('attribute3','attribute4');
    }
}
new foo();

there was a comment before "new foo();" in this code (written by someone
else) that said:

"need to instantiate class to fill static members. I don't like this
setup, but haven't found a better way yet to have const members of class or
interface be instantiated objects rather than constant expressions."

It happens frequently enough.  In this code that I found, an accidental
assignment in an if statement breaks other calling code due to lack of
final.  Lack of load-time static initialisation means that class members
have to be instantiated by a call outside the class definition, and that
every member (the real class has about 100 members) has to be defined
twice.

I've also seen code like:

final class my_things {
    private $name;
    private static $all_things = array();
    function __construct($name,$otherstuff) {
        $this->name=$name;
        ....
        self::$all_things[$name] = $this;
    }
    static function get_by_name($name) { 
        return self::$all_things[$name]; 
    }
}

new my_things('thing1',...);
new my_things('thing2',...);
....

which, is also far less than ideal... and doesn't maintain any usable
reference to the actual enumeration.  Each one must be looked up by it's
reference string, often defined elsewhere as a series of consts.  It can
also be added to since the constructor must be public.

The closest you can come to getting a real enum in php is to use public
static final functions to get the enumerated values.  This requires a lot
of plumbing code, i.e., a factory method that caches values so new ones are
not constructed on every call (because we want to boolean::TRUE() ===
boolean::TRUE() not just ==, etc), and an entire function definition in
which each enumerated value is instantiated/returned.

The late static binding feature being added in 5.3 might enable someone to
write an enum superclass (function based) getting around *some* of this
plumbing code, but using functions as enumerations would still be an ugly
hack.

There are so many places where this is useful.  Say I want to add a list
of log levels to a logging class.  I want each log level to be a numeric
value that can be compared, and have a string representation that can be
printed.  It can't be done in any safe, non-repetitive, object oriented,
clean way.



Reproduce code:
---------------
n/a

Expected result:
----------------
n/a

Actual result:
--------------
n/a

-- 
Edit bug report at http://bugs.php.net/?id=48277&edit=1
-- 
Try a CVS snapshot (PHP 5.2):        
http://bugs.php.net/fix.php?id=48277&r=trysnapshot52
Try a CVS snapshot (PHP 5.3):        
http://bugs.php.net/fix.php?id=48277&r=trysnapshot53
Try a CVS snapshot (PHP 6.0):        
http://bugs.php.net/fix.php?id=48277&r=trysnapshot60
Fixed in CVS:                        
http://bugs.php.net/fix.php?id=48277&r=fixedcvs
Fixed in CVS and need be documented: 
http://bugs.php.net/fix.php?id=48277&r=needdocs
Fixed in release:                    
http://bugs.php.net/fix.php?id=48277&r=alreadyfixed
Need backtrace:                      
http://bugs.php.net/fix.php?id=48277&r=needtrace
Need Reproduce Script:               
http://bugs.php.net/fix.php?id=48277&r=needscript
Try newer version:                   
http://bugs.php.net/fix.php?id=48277&r=oldversion
Not developer issue:                 
http://bugs.php.net/fix.php?id=48277&r=support
Expected behavior:                   
http://bugs.php.net/fix.php?id=48277&r=notwrong
Not enough info:                     
http://bugs.php.net/fix.php?id=48277&r=notenoughinfo
Submitted twice:                     
http://bugs.php.net/fix.php?id=48277&r=submittedtwice
register_globals:                    
http://bugs.php.net/fix.php?id=48277&r=globals
PHP 4 support discontinued:          http://bugs.php.net/fix.php?id=48277&r=php4
Daylight Savings:                    http://bugs.php.net/fix.php?id=48277&r=dst
IIS Stability:                       
http://bugs.php.net/fix.php?id=48277&r=isapi
Install GNU Sed:                     
http://bugs.php.net/fix.php?id=48277&r=gnused
Floating point limitations:          
http://bugs.php.net/fix.php?id=48277&r=float
No Zend Extensions:                  
http://bugs.php.net/fix.php?id=48277&r=nozend
MySQL Configuration Error:           
http://bugs.php.net/fix.php?id=48277&r=mysqlcfg

Reply via email to