我是PHP中OOP的新手。我有以下问题:我有 1 个名为"用户"的父类和 2 个子类"业务"和"标准"。
我的父类看起来像这样:
class User {
protected $m_iId;
protected $m_iFoto;
protected $m_sEmail;
/*Constructor*/
public function __construct(){
$this->Id = -1;
$this->Foto = "";
$this->Email = "";
}
/*Setter*/
public function __set($p_sProperty, $p_sValue){
switch($p_sProperty){
case "Id":
if(is_numeric($p_sValue) && $p_sValue !== -1){
$iNumber = intVal($p_sValue);
if($iNumber >= -1){
$this->m_iId = $p_sValue;
}
else{
echo("Not a valid id: ".$p_sValue);
}
}
break;
case "Foto":
if(is_numeric($p_sValue) && $p_sValue !== -1){
$iNumber = intVal($p_sValue);
if($iNumber >= -1){
$this->m_iFoto = $p_sValue;
}
else{
echo("Not a valid Foto_id: ".$p_sValue);
}
}
break;
case "Email":
$this->m_sEmail = $p_sValue;
break;
default: echo("Unknown property: ".$p_sProperty);
}
}
/*Getter*/
public function __get($p_sProperty){
$vResult = null;
switch($p_sProperty){
case "Id";
$vResult = $this->m_iId;
break;
case "Foto";
$vResult = $this->m_iFoto;
break;
case "Email";
$vResult = $this->m_sEmail;
break;
default: echo("Unknown property: ".$p_sProperty);
}
return $vResult;
}
}
一个孩子看起来像这样:
class UserStandaard extends User {
//velden die bereikbaar zijn
protected $m_sName;
/*Constructor*/
public function __construct(){
parent::__construct();
$this->Name = "";
}
/*Setter*/
public function __set($p_sProperty, $p_sValue){
switch($p_sProperty){
case "Name":
$this->m_sName = $p_sValue;
break;
default: echo("Unknown property: ".$p_sProperty);
}
}
/*Getter*/
public function __get($p_sProperty){
$vResult = null;
switch($p_sProperty){
case "Name";
$vResult = $this->m_sName;
break;
default: echo("Unknown property: ".$p_sProperty);
}
return $vResult;
}
}
我的问题如下:如何申请 ID?我想做这样的事情:
$oUser = new UserStandaard();
echo $oUser->Id;
但这行不通...它不断回响
Unknown property: Id
谢谢!!
问题是__get
和__set
的派生类实现不调用基类实现。这不会自动发生,您需要明确执行此操作:
class UserStandaard extends User {
/*Setter*/
public function __set($p_sProperty, $p_sValue){
parent::__set($p_sProperty, $p_sValue);
// your current code follows
}
}
但是,这仍然不起作用,因为现在您的父实现将仅识别它知道的三个属性。似乎没有直接的方法来处理这个问题,这意味着你的设计是有问题的,需要修改。
可能的解决方案
结构__get
和__set
更易于插入(示例待定)。我的意思是,他们识别的属性集不应该被硬编码,因为这使得扩展它们变得非常困难。理想情况下,您需要为每个属性使用不同的 getter 和 setter:
class User {
public function getName() { ... }
public function setName($name) { ... }
}
这将让你保持代码漂亮、干净和分离。然后,您可以连接__get
和__set
以转发到以下方法:
public function __get($name)
{
$getter = 'get'.ucfirst($name);
if (!method_exists($this, $getter)) {
die("This object does not have a $name property or a $getter method.");
}
return $this->$getter();
}
public function __set($name, $value)
{
$setter = 'set'.ucfirst($name);
if (!method_exists($this, $setter)) {
die("This object does not have a $name property or a $setter method.");
}
$this->$setter($value);
}
通过这种方式,您可以将每个属性分解为如上所述的 getter 和 setter 方法,并且绝对不需要重写派生类中的 __get
和 __set
。只需为您感兴趣的属性声明额外的 getter 和 setter,基类 __get
/__set
将正确转发到这些方法。
在 UserStandaard 类的重写__get()
方法中没有 Id。
/*Getter*/
public function __get($p_sProperty){
$vResult = null;
switch($p_sProperty){
case "Name";
$vResult = $this->m_sName;
break;
default: echo("Unknown property: ".$p_sProperty);
}
return $vResult;
}
但你可能会想,这是在他的父母身上。
否,因为您已经覆盖了父母方法。
您正在尝试使用 __get 和 __set 在 User 类中使用魔术方法重载属性,但是您在 UserStandaaard 类中重写了这些函数。这两个函数都只从自己的类中知道自己的属性,因为 Userstandaard 的 __get 方法不会调用它的父方法。但即使你这样做了,它也会失败,因为你如何使用开关大小写和不同的属性名称实现你的魔术方法。
因此,在 UserStandaard 中使用魔术方法将只知道 1 个属性,如果您从 User 调用父方法,它将只知道父属性(如 Jon 提到的)。
我会说改变你的设计,这是行不通的。
乔恩有一个很好的例子来说明它是如何工作的!
哦,还有对你喊道:Welkom bij stack-overflow! ;)