Ta statyczna metoda factory i te chain methods są o tyle fajne że mogą posłużyć do takich zabaw:
abstract class Number
{
protected $_value;
public static function factory($model, $value = 0)
{
$class = 'Number' . ucfirst($model);
return new $class($value);
}
public function increment($number = 1)
{
$this->_value += $number;
return $this;
}
public function __construct($value = 0)
{
$this->_value = $value;
}
abstract public function value();
abstract public function __toString();
}
class NumberInteger extends Number
{
private $_as_hex = FALSE;
private $_fix = NULL;
public function as_hex($fix = NULL)
{
$this->_as_hex = TRUE;
$this->_fix = $fix;
return $this;
}
public function value()
{
return (int) $this->_value;
}
public function __toString()
{
if ($this->_as_hex === TRUE)
{
return ($this->_fix !== NULL)
? sprintf('%0' . $this->_fix . 'x', $this->_value)
: dechex($this->_value);
}
return (string) $this->_value;
}
}
class NumberDecimal extends Number
{
public static $decimals = 6;
public function value()
{
return number_format($this->_value, self::$decimals, '.', '');
}
public function __toString()
{
return $this->value();
}
}
// test
// Integer values
$integer1 = Number::factory('Integer', 301)
->as_hex(4)
->increment(2);
$integer2 = Number::factory('Integer', 521)
->as_hex()
->increment(1);
$integer3 = Number::factory('Integer', 122)
->increment(122);
// Decimal values
NumberDecimal::$decimals = 4;
$decimal1 = Number::factory('Decimal', 20)
->increment(5.0001);
$decimal2 = Number::factory('Decimal', 1)
->increment(1);
$decimal3 = Number::factory('Decimal', $decimal1->value())
->increment($decimal2->value());
echo "Integer1: " . $integer1;
echo "\n";
echo "Integer2: " . $integer2;
echo "\n";
echo "Integer3: " . $integer3;
echo "\n";
echo "Decimal1: " . $decimal1;
echo "\n";
echo "Decimal2: " . $decimal2;
echo "\n";
echo "Decimal3: " . $decimal3;
wynik:
Integer1: 012f
Integer2: 20a
Integer3: 244
Decimal1: 25.0001
Decimal2: 2.0000
Decimal3: 27.0001
W tym założeniu jest ten prefix klas czyli klasy rozszerzające klasę abstrakcyjną muszą się nazywać odpowiednio: NumberInteger, NumberDecimal, NumberFloat itd..., choć oczywiście można przyjąć inne podejście. Uczestniczyłem kiedyś w procesie rekrutacji i byłem na rozmowie na stanowisko Junior PHP, to nie jest taka prosta sprawa, wydaje mi się że jest to na zasadzie podoba się/*nie podoba się, wynik był odmowny, nie wiem kogo właściwie szukali. Powyższe podejście i styl nazewnictwa są stosowane w niektórych frameworkach, tych mniej popularnych, nie działam w Symfony (z tym była związana rekrutacja). Stąd też wątpliwe żeby chodziło tylko o kompetencje w samym czystym PHP.