-
Notifications
You must be signed in to change notification settings - Fork 0
Usage
An enumeration type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.
Because they are constants, the names of an enumeration type's fields are in uppercase letters.
You define an enumeration type by extending the abstract class FlorianWolters\Component\Core\Enum\EnumAbstract. For example, you would specify a days-of-the-week enumeration type as:
<?php
namespace FlorianWolters\Mock;
use FlorianWolters\Component\Core\Enum\EnumAbstract;
final class DayEnum extends EnumAbstract
{
// @codingStandardsIgnoreStart
/**
* The day *sunday*.
*
* @return DayEnum The day *sunday*.
*/
final public static function SUNDAY()
{
return self::getInstance();
}
/**
* The day *monday*.
*
* @return DayEnum The day *monday*.
*/
final public static function MONDAY()
{
return self::getInstance();
}
/**
* The day *tuesday*.
*
* @return DayEnum The day *tuesday*.
*/
final public static function TUESDAY()
{
return self::getInstance();
}
/**
* The day *wednesday*.
*
* @return DayEnum The day *wednesday*.
*/
final public static function WEDNESDAY()
{
return self::getInstance();
}
/**
* The day *thursday*.
*
* @return DayEnum The day *thursday*.
*/
final public static function THURSDAY()
{
return self::getInstance();
}
/**
* The day *friday*.
*
* @return DayEnum The day *friday*.
*/
final public static function FRIDAY()
{
return self::getInstance();
}
/**
* The day *saturday*.
*
* @return DayEnum The day *saturday*.
*/
final public static function SATURDAY()
{
return self::getInstance();
}
// @codingStandardsIgnoreEnd
}You should use enumeration types any time you need to represent a fixed set of constants. That includes natural enumeration types such as the planets in our solar system and data sets where you know all possible values at compile time - for example, the choices on a menu, command line flags, and so on. Here is some code that shows you how to use the DayEnum enumeration defined above:
<?php
namespace FlorianWolters;
use FlorianWolters\Mock\DayEnum;
final class DayEnumExample
{
/**
* @var DayEnum
*/
private $day;
/**
* @param DayEnum $day
*/
public function __construct(DayEnum $day)
{
$this->day = $day;
}
/**
* @return void
*/
public function tellItLikeItIs()
{
switch ($this->day) {
case DayEnum::MONDAY():
print("Mondays are bad.\n");
break;
case DayEnum::FRIDAY():
print("Fridays are better.\n");
break;
case DayEnum::SATURDAY():
case DayEnum::SUNDAY():
print("Weekends are best.\n");
break;
default:
print("Midweek days are so-so.\n");
break;
}
}
/**
* Runs this {@see DayEnumExample}.
*
* @param integer $argc The number of arguments.
* @param string[] $argv The arguments.
*
* @return integer Always `0`.
*/
public static function main($argc, array $argv = [])
{
$firstDay = new self(DayEnum::MONDAY());
$firstDay->tellItLikeItIs();
$thirdDay = new self(DayEnum::WEDNESDAY());
$thirdDay->tellItLikeItIs();
$fifthDay = new self(DayEnum::FRIDAY());
$fifthDay->tellItLikeItIs();
$sixthDay = new self(DayEnum::SATURDAY());
$sixthDay->tellItLikeItIs();
$seventhDay = new self(DayEnum::SUNDAY());
$seventhDay->tellItLikeItIs();
return 0;
}
}
exit(DayEnumExample::main($argc, $argv));The output is:
Mondays are bad.
Midweek days are so-so.
Fridays are better.
Weekends are best.
Weekends are best.
Enumeration types implemented with FlorianWolters\Component\Core\Enum are much more powerful than other implementations. A class which extends the abstract class FlorianWolters\Component\Core\Enum\EnumAbstract defines a so-called enumeration type. The enumeration class body can include methods and other fields. The abstract class adds some special methods when it creates an enumeration. For example, they have a static values method that returns an array containing all of the values of the enumeration in the order they are declared. This method is commonly used in combination with the foreach construct to iterate over the values of an enum type. For example, this code from the PlanetEnum class example below iterates over all the planets in the solar system.
<?php
$format = "Your weight on %s is %f\n";
/* @var $planet PlanetEnum */
foreach (PlanetEnum::values() as $planet) {
$surfaceWeight = $planet->surfaceWeight($mass);
\printf($format, $planet, $surfaceWeight);
}Note: All enumerations must explicitly extend FlorianWolters\Component\Core\Enum\EnumAbstract.
In the following example, PlanetEnum is an enumeration type that represents the planets in the solar system. They are defined with constant mass and radius properties.
Each enumeration constant is declared with values for the mass and radius parameters. These values are passed to the constructor of the enumeration type when the constant is created.
Note: The constructor for an enumeration type must have the name construct. The name differs from the name of the constructor, the magic method __construct.
Note: The constructor for an enumeration type must have protected or private access. You cannot invoke an enumeration constructor yourself.
In addition to its properties and constructor, PlanetEnum has methods that allow you to retrieve the surface gravity and weight of an object on each planet. Here is a sample program that takes your weight on earth (in any unit) and calculates and prints your weight on all of the planets (in the same unit):
<?php
namespace FlorianWolters;
use FlorianWolters\Component\Core\Enum\EnumAbstract;
final class PlanetEnum extends EnumAbstract
{
/**
* The universal gravitational constant.
*
* @var float
*/
const G = 6.67300e-11;
/**
* The mass of this planet in kilograms.
*
* @var float
*/
private $mass;
/**
* The radius of this planet in meters.
*
* @var float
*/
private $radius;
// @codingStandardsIgnoreStart
/**
* The planet mercury.
*
* @return PlanetEnum The planet mercury.
*/
final public static function MERCURY()
{
return self::getInstance(3.303e23, 2.4397e6);
}
/**
* The planet venus.
*
* @return PlanetEnum The planet venus.
*/
final public static function VENUS()
{
return self::getInstance(4.869e24, 6.0518e6);
}
/**
* The planet earth.
*
* @return PlanetEnum The planet earth.
*/
final public static function EARTH()
{
return self::getInstance(5.976e24, 6.37814e6);
}
/**
* The planet mars.
*
* @return PlanetEnum The planet mars.
*/
final public static function MARS()
{
return self::getInstance(6.421e23, 3.3972e6);
}
/**
* The planet jupiter.
*
* @return PlanetEnum The planet jupiter.
*/
final public static function JUPITER()
{
return self::getInstance(1.9e27, 7.1492e7);
}
/**
* The planet saturn.
*
* @return PlanetEnum The planet saturn.
*/
final public static function SATURN()
{
return self::getInstance(5.688e26, 6.0268e7);
}
/**
* The planet uranus.
*
* @return PlanetEnum The planet uranus.
*/
final public static function URANUS()
{
return self::getInstance(8.686e25, 2.5559e7);
}
/**
* The planet neptune.
*
* @return PlanetEnum The planet neptune.
*/
final public static function NEPTUNE()
{
return self::getInstance(1.024e26, 2.4746e7);
}
// @codingStandardsIgnoreEnd
/**
* Constructs a new planet with the specified mass and the specified radius.
*
* The name of the constructor of a functional enumeration is `construct` by
* convention and must have the visibility `protected` or `private`.
*
* @param float $mass The mass in kilograms.
* @param float $radius The radius in meters.
*/
protected function construct($mass, $radius)
{
$this->mass = $mass;
$this->radius = $radius;
}
/**
* Returns the mass of this planet.
*
* @return float The mass in kilograms.
*/
public function getMass()
{
return $this->mass;
}
/**
* Returns the radius of this planet.
*
* @return float The radius in meters.
*/
public function getRadius()
{
return $this->radius;
}
/**
* Calculates and returns the surface gravity of this planet.
*
* @return float The surface gravity.
*/
public function surfaceGravity()
{
return ((self::G * $this->mass) / ($this->radius * $this->radius));
}
/**
* Calculates and returns the surface weight of this planet.
*
* @param float $otherMass Another mass in kilograms.
*
* @return float The surface weight.
*/
public function surfaceWeight($otherMass)
{
return ($this->surfaceGravity() * $otherMass);
}
/**
* Runs this {@see PlanetEnumExample}.
*
* @param integer $argc The number of arguments.
* @param string[] $argv The arguments.
*
* @return integer Always `0`.
*/
public static function main($argc, array $argv = [])
{
if (2 !== $argc) {
echo "Usage: php FunctionalEnumExample <earth_weight>" . \PHP_EOL;
return -1;
}
$earthWeight = (float) $argv[1];
$mass = ($earthWeight / PlanetEnum::EARTH()->surfaceGravity());
$format = "Your weight on %s is %f\n";
/* @var $planet PlanetEnum */
foreach (PlanetEnum::values() as $planet) {
$surfaceWeight = $planet->surfaceWeight($mass);
\printf($format, $planet, $surfaceWeight);
}
return 0;
}
}
exit(PlanetEnumExample::main($argc, $argv));
If you run PlanetEnumExample.php from the command line with an argument of 175, you get this output:
$ php PlanetEnumExample.php 175
Your weight on MERCURY is 66.107583
Your weight on VENUS is 158.374842
Your weight on EARTH is 175.000000
Your weight on MARS is 66.279007
Your weight on JUPITER is 442.847567
Your weight on SATURN is 186.552719
Your weight on URANUS is 158.397260
Your weight on NEPTUNE is 199.207413
In PHP, the Singleton design pattern is implemented by using the Creation Method (see Implementation Patterns Item 8.16) implementation pattern. Usually a static creation method with the name getInstance is used to create and return the instance.
With FlorianWolters\Component\Core\Enum there is one more way to implement the Singleton creational design pattern. For example, you would specify a simple Singleton enumeration type as:
<?php
namespace FlorianWolters\Mock;
use FlorianWolters\Component\Core\Enum\EnumAbstract;
final class SingletonEnum extends EnumAbstract
{
// @codingStandardsIgnoreStart
/**
* The *Singleton* instance of this class.
*
* @return SingletonEnum The *Singleton* instance.
*/
final public static function INSTANCE()
{
return self::getInstance();
}
/**
* Returns the string representation of this instance.
*
* This method implements the *Debug Print Method* implementation pattern.
*
* @return string The string representation.
*/
public function __toString()
{
return __CLASS__;
}
// @codingStandardsIgnoreEnd
}The following code shows you how to use the SingletonEnum enumeration defined above:
<?php
\var_dump(SingletonEnum::INSTANCE()->__toString());
\var_dump(SingletonEnum::INSTANCE() === SingletonEnum::INSTANCE());The output is:
string(33) "FlorianWolters\Mock\SingletonEnum"
bool(true)
This implementation is based on the Java implementation introduced by Joshua Bloch (see Effective Java Item 3) and has been adapted and abstracted for PHP.
- J. Bloch. Effective Java, 2nd Edition. Boston: Addison-Wesley, 2008.
- K. Beck. Implementation Patterns. Boston: Addison-Wesley, 2008.