-
Notifications
You must be signed in to change notification settings - Fork 1
Closed
Labels
Description
Scope of Change
There will be a defined way to write enums.
Rationale
Interaction with programming languages with enums, via EASC, for example.
Functionality
Core
A new class, lang.Enum will be added:
<?php
/**
* Enumeration
*
* @purpose Abstract base class
*/
abstract class Enum extends Object {
public
$name = '';
protected
$ordinal = 0;
/**
* Constructor
*
* @param int ordinal default 0
* @param string name default ''
*/
protected function __construct($ordinal= 0, $name= '') {
$this->ordinal= $ordinal;
$this->name= $name;
}
/**
* Returns the enumeration member uniquely identified by
*
* @param lang.XPClass
* @param string name enumeration member
* @return lang.Enum
* @throws lang.IllegalArgumentException
*/
public static function valueOf(XPClass $class, $name) {
// ...
}
/**
* Create a string representation of this enum
*
* @return string
*/
public function toString() {
return $this->name;
}
/**
* Returns all members for a given enum.
*
* @param string class
* @return lang.Enum[]
*/
protected static function membersOf($class) {
$c= new ReflectionClass($class);
return array_values($c->getStaticProperties());
}
}
?>
Reflection
The XPClass class will support an isEnum() method
<?php
/**
* Determines if this XPClass object represents an enum type.
*
* @return bool
*/
public function isEnum() {
// ...
}
?>
Defining an enum
To create an enum type, the following is necessary:
- Create public static members with the enum names
Unfortunately, it is not possible to use class constants because these
can only be initialized to scalars or constant arrays in PHP. - Define a static initializer and initialize them
PHP does not allow initializing member variables to objects. - Implement the values() method with the boilerplate shown below.
It cannot be enforced that a static values() method should exist, as
adding public static abstract function values(); to the base class
will raise an E_STRICT "Static function Enum::values() should not
be abstract"
<?php
class TransactionType extends Enum {
public static
$NOT_SUPPORTED,
$REQUIRED,
$SUPPORTS,
$REQUIRES_NEW,
$MANDATORY,
$NEVER,
$UNKNOWN;
static function __static() {
self::$NOT_SUPPORTED= new self(0, 'NOT_SUPPORTED');
self::$REQUIRED= new self(1, 'REQUIRED');
self::$SUPPORTS= new self(2, 'SUPPORTS');
self::$REQUIRES_NEW= new self(3, 'REQUIRES_NEW');
self::$MANDATORY= new self(4, 'MANDATORY');
self::$NEVER= new self(5, 'NEVER');
self::$UNKNOWN= new self(6, 'UNKNOWN');
}
public static function values() {
return parent::membersOf(__CLASS__);
}
}
?>
Usage: Enum values
Enum values can be accessed by the following syntax:
<?php
$transactionType= TransactionType::$MANDATORY;
?>
Note:
Because class members cannot be final in PHP enum members can actually
be modified at run-time. It is not possible to use class constants for
the afforementioned reasons.
Usage: Type-safety
Because enums are essentially classes, they can be used as type hints:
<?php
class MethodWrapper extends Object {
public function setTransactionType(TransactionType $t) {
$this->transactionType= $t;
}
}
?>
Usage: Printing
The following will print "MANDATORY" to the console:
<?php
Console::writeLine(TransactionType::$MANDATORY);
?>
Usage: Using enums in switch
<?php
$transactionType= TransactionType::$MANDATORY;
// ...later on:
switch ($transactionType) {
case TransactionType::$MANDATORY: {
// ...
break;
}
case TransactionType::$NEVER: {
// ...
break;
}
}
?>
Note:
Nothing special, really. PHP supports this as-is.
Usage: Enum values
The following will print all transaction type values to the console:
<?php
foreach (TransactionType::values() as $type) {
Console::writeLine('- ', $type);
}
?>
Example: Coin
<?php
// Definition
class Coin extends Enum {
public static
$penny,
$nickel,
$dime,
$quarter;
static function __static() {
self::$penny= new self(1, 'penny');
self::$nickel= new self(2, 'nickel');
self::$dime= new self(10, 'dime');
self::$quarter= new self(25, 'quarter');
}
public static function values() {
return parent::membersOf(__CLASS__);
}
public function value() {
return $this->ordinal;
}
public function color() {
switch ($this) {
case self::$penny: return 'copper';
case self::$nickel: return 'nickel';
case self::$dime: case self::$quarter: return 'silver';
}
}
}
// Usage
foreach (Coin::values() as $coin) {
echo $coin->name, ': ', $coin->value(), '¢ (', $coin->color(), ")\n";
}
?>
The above example prints out the following:
penny: 1¢ (copper)
nickel: 5¢ (nickel)
dime: 10¢ (silver)
quarter: 25¢ (silver)
Security considerations
n/a
Speed impact
n/a
Dependencies
This will increase the minor version
Related documents
- xp-framework/rfc Typesafe enumerations (PHP5) #9: Typesafe enumerations (PHP5)
Enum support in PHP5 with patched Zend Engine - http://experiments.xp-framework.net/?arena,enum
Experiments and demos - http://xp-framework.info/xml/xp.en_US/news/view?199
EASC and enums - http://xp-framework.info/xml/xp.en_US/news/view?207
Enum usecases: Profiling