對於同一個類,我需要不同的__toString()
。在運行時切換的PHP多個__toString方法
我有一個包含一個姓名和一個姓Person類。根據目前的情況下我希望與不同的順序來顯示它,格式化等等。試想一下三種情形:
- 的名字是第一位的,其次是空間和姓
Thomas Müller
- 姓至上和大寫,後面的空間和姓名
MÜLLER Thomas
- 姓至上,其次是逗號,則空間和姓名
Müller, Thomas
我可以爲每個顯示公共方法。
<meta charset='utf-8'/>
<?php
class Person
{
protected $firstname;
protected $surname;
public function __construct($firstname, $surname)
{
$this->firstname = $firstname;
$this->surname = $surname;
}
public function toStringWithFirstnameFirst()
{
return $this->firstname . " " . $this->surname;
}
public function toStringWithSurnameFirstUppercase()
{
$surnameConverted = mb_convert_case($this->surname, MB_CASE_UPPER, "UTF-8");
return $surnameConverted . " " . $this->firstname;
}
public function toStringWithSurnameFirstAndFirstnameAfterComma()
{
return $this->surname . ", " . $this->firstname;
}
}
$person = new Person("Thomas", "Müller");
echo $person->toStringWithFirstnameFirst() . "<br/>";
echo $person->toStringWithSurnameFirstUppercase() . "<br/>";
echo $person->toStringWithSurnameFirstAndFirstnameAfterComma() . "<br/>";
?>
但我堅持DescriptiveButVeryLongToStringMethodNames
。 我希望在代碼中只有echo $person;
。
解決方案:存儲在所述靜態成員
我的第一個解決方案是將switch-case
內部__toString()
方法的類的狀態。條件語句取決於存儲在靜態變量self::$chosenToStringMethod
中的類別狀態。所以我需要靜態方法來設置類的狀態以及用作枚舉的類常量。
<meta charset='utf-8'/>
<?php
class Person
{
protected $firstname;
protected $surname;
const PRINT_FIRSTNAME_FIRST = 1;
const PRINT_SURNAME_FIRST_UPPERCASE = 2;
const PRINT_SURNAME_FIRST_FIRSTNAME_AFTER_COMMA = 3;
static private $chosenToStringMethod;
public function __construct($firstname, $surname)
{
$this->firstname = $firstname;
$this->surname = $surname;
}
static public function setToStringMethod($choice)
{
self::$chosenToStringMethod = $choice;
}
private function toStringWithFirstnameFirst()
{
return $this->firstname . " " . $this->surname;
}
private function toStringWithSurnameFirstUppercase()
{
$surnameConverted = mb_convert_case($this->surname, MB_CASE_UPPER, "UTF-8");
return $surnameConverted . " " . $this->firstname;
}
private function toStringWithSurnameFirstAndFirstnameAfterComma()
{
return $this->surname . ", " . $this->firstname;
}
public function __toString()
{
switch (self::$chosenToStringMethod) {
case self::PRINT_FIRSTNAME_FIRST:
return $this->toStringWithFirstnameFirst();
break;
case self::PRINT_SURNAME_FIRST_UPPERCASE:
return $this->toStringWithSurnameFirstUppercase();
break;
case self::PRINT_SURNAME_FIRST_FIRSTNAME_AFTER_COMMA:
return $this->toStringWithSurnameFirstAndFirstnameAfterComma();
break;
default:
return "No __toString method set";
break;
}
}
}
$person = new Person("Thomas", "Müller");
echo $person . "<br/>";
Person::setToStringMethod(Person::PRINT_FIRSTNAME_FIRST);
echo $person . "<br/>";
Person::setToStringMethod(Person::PRINT_SURNAME_FIRST_UPPERCASE);
echo $person . "<br/>";
Person::setToStringMethod(Person::PRINT_SURNAME_FIRST_FIRSTNAME_AFTER_COMMA);
echo $person . "<br/>";
?>
我看到這個解決方案的一些缺點:
Person
類是越來越沉重switch-case
語句可以隱藏一些錯誤
我希望只包含它自己的功能Person
類不是所有類型的toStrings。我寧願有一些可以動態注入__toString()
的模式。
那麼,你在哪裏以及如何決定輸出哪種格式?這可以從一行改變到另一行嗎?那麼爲此設置一個全局配置是沒有意義的。 'echo $ person-> name(Person :: FORMAL)'';即用一堆預定義的可能格式傳遞一個參數? – deceze
我不確定你在這裏期待什麼;你的第一個缺點似乎是不可避免的,我不明白你的意思。如果有某種方式「動態地注入__toString」,那麼代碼就會生存在某個地方。 「switch」聲明似乎不像其他任何實現那樣可能隱藏錯誤。 – IMSoP
或者有一個專用的,可配置的*渲染器*。這看起來很管用,但從長遠來看,它使事情變得簡單。 – Yoshi