Implementing Enum Using Late Static Binding in PHP
Reading Time:
Reading Time:
If we try to access a static method with same signature in both the extended class and extending class then the method resolves only to the class method that it is defined in.
<?php
class Foo {
public static function whoami() {
echo __CLASS__;
}
public static function staticAccess() {
self::whoami();
}
}
class Baz extends Foo {
public static function whoami() {
echo __CLASS__;
}
}
Baz::staticAccess();
?>
Foo
The above example will output Foo as the method whoami
is declared inside the Foo class.
With the help of late static binding we can access the method inside the class that is used to access it using the static keyword. From the above example, instead of self::whoami
in the staticAccess()
method, we need to place static::staticAccess()
. This way when we access staticAccess()
method using Baz
class it will output Baz.
<?php
class Foo {
public static function whoami() {
echo __CLASS__;
}
public static function staticAccess() {
static::whoami();
}
}
class Baz extends Foo {
public static function whoami() {
echo __CLASS__;
}
}
Baz::staticAccess();
?>
Foo
I have used Late Static Binding to create a set of Interface and Abstract class to implement this enum.
interface IEnum {
/**
* Only concrete class should implement this function that should behave as
* an enum.
*
* This method should return the __CLASS__ constant property of that class
*
* @return string __CLASS__
*/
public static function who();
}
abstract class Enum {
/**
* The selected value for the enum implementation
*
* @var mixed
*/
public $value;
public function __construct($value) {
$this->value = $value;
}
/**
* The factory method that creates the corresponding enum class.
*
* @param integer $type
* @return false|class
*/
public static function Factory($type) {
if (empty($type)) {
return false;
}
// use of late static binding to get the class.
$class = static::who();
if (array_key_exists($type, static::$_enums)) {
return new $class($type);
}
return false;
}
public function getValue() {
return $this->value;
}
public static function getValues() {
return array_keys(static::$_enums);
}
public function getString() {
return static::$_enums[$this->value];
}
public function __toString() {
return static::$_enums[$this->value];
}
}
class Fruits extends Enum implements IEnum {
public static $_enums = array(
1 => 'Apple'
2 => 'Orange'
3 => 'Banana'
)
public static function who() {
return __CLASS__;
}
}
// user input from dropdown menu of fruits list
$input = 3;
$fruit = Fruits::Factory($input);
$fruit->getValue();
$fruit->getString();
3
Banana
Let me know your thoughts on this in the comments.