我正在使用PHP实现OOP设计。我想知道PHP如何为其神奇的方法(如__get和__set )处理继承。
class Foo
{
protected $property1;
public function __get($name)
{
if ($name == "property1")
{
// do some logic
return $result; // may be null
}
return;
}
public function __set($name, $value)
{
if ($name == "property1")
{
// do some logic
return $result; // may be null
}
result;
}
}
现在用于扩展Foo
class Bar extends Foo
{
protected $property2;
public function __get($name)
{
if (($result = parent::__get($name)) !== null)
return $result; // may be null
if ($name == "property2")
{
// do some logic
return $result; // may be null
}
return;
}
public function __set($name, $value)
{
if (($result = parent::__set($name, $value)) !== null)
return $result; // may be null
if ($name == "property2")
{
// do some logic
return $result; // may be null
}
return;
}
}
当PHP将null
作为一个函数的结果返回时,没有什么可返回的.这可能导致parent::__get()
或parent::__set()
是否真实返回null,还是返回时不带值,从而导致开销。
现在,如果PHP首先考虑static::_get()
和static::__set()
,并在失败时退回到parent
版本,则可以将其简化为:
class Bar extends Foo
{
protected $property2;
public function __get($name)
{
if ($name = "property2")
{
// do some logic
return $result; // may be null
}
return;
}
public function __set($name, $value)
{
if ($name = "property2")
{
// do some logic
return $result; // may be null
}
return;
}
}
我无法在当前实现上测试它,因为上下文中的类操作生产、活动数据库。哪个是正确的实现?
谢谢!
发布于 2014-10-21 07:27:04
只使用魔术方法作为代理方法。您的代码将更加简洁,您不需要处理继承带来的问题。
简单的例子:
class Foo
{
protected $property1;
public function setProperty1($property1)
{
// do some logic
$this->property1 = $property1;
return $this;
}
public function getProperty1()
{
// do some logic
return $this->property1;
}
public function __get($name)
{
$method = 'get' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->$method();
}
}
public function __set($name, $value)
{
$method = 'set' . ucfirst($name);
if (method_exists($this, $method)) {
$this->$method($value);
}
}
}
class Bar extends Foo
{
protected $property2;
public function setProperty2($property2)
{
// do some logic
$this->property2 = $property2;
return $this;
}
public function getProperty2()
{
// do some logic
return $this->property2;
}
}
示例呼叫:
$bar = new Bar;
$bar->property1 = 'foo';
$bar->property2 = 'bar';
var_dump($bar);
发布于 2014-10-21 07:25:36
我已经成功地创建了一个孤立的环境并测试了这两种方法。
方法1
class Foo
{
protected $property1;
public function __get($name)
{
if ($name == "name")
{
echo "been here @line(" . __LINE__ . ") Foo::__get('$name') <br/>";
$result = $this->property1;
return $result; // may be null
}
return;
}
public function __set($name, $value)
{
if ($name == "name")
{
echo "been here @line(" . __LINE__ . ") Foo::__set('$name', '$value') <br/>";
$result = $this->property1 = $value;
return $result; // may be null
}
return;
}
}
class Bar extends Foo
{
protected $property2;
public function __get($name)
{
if ($name == "place")
{
echo "been here @line(" . __LINE__ . ") Bar::__get('$name') <br/>";
$result = $this->property2;
return $result; // may be null
}
return;
}
public function __set($name, $value)
{
if ($name == "place")
{
echo "been here @line(" . __LINE__ . ") Bar::__set('$name', '$value') <br/>";
$result = $this->property2 = $value;
return $result; // may be null
}
return;
}
}
$bar = new Bar;
$bar->name = 'Alice';
$bar->place = 'Wonderland';
echo "done that: '{$bar->name} in {$bar->place}'";
上述代码的结果如下:
been here @line(59) Bar::__set('place', 'Wonderland')
been here @line(43) Bar::__get('place')
done that: ' in Wonderland'
这显然不是答案。
方法2
class Foo
{
protected $property1;
public function __get($name)
{
if ($name == "name")
{
echo "been here @line(" . __LINE__ . ") Foo::__get('$name') <br/>";
$result = $this->property1;
return $result; // may be null
}
return;
}
public function __set($name, $value)
{
if ($name == "name")
{
echo "been here @line(" . __LINE__ . ") Foo::__set('$name', '$value') <br/>";
$result = $this->property1 = $value;
return $result; // may be null
}
return;
}
}
class Bar extends Foo
{
protected $property2;
public function __get($name)
{
if (($result = parent::__get($name)) !== null)
{
echo "been here @line(" . __LINE__ . ") parent::__get('$name') <br/>";
return $result; // may be null
}
if ($name == "place")
{
echo "been here @line(" . __LINE__ . ") Bar::__get('$name') <br/>";
$result = $this->property2;
return $result; // may be null
}
return;
}
public function __set($name, $value)
{
if (($result = parent::__set($name, $value)) !== null)
{
echo "been here @line(" . __LINE__ . ") parent::__set('$name', '$value') <br/>";
return $result; // may be null
}
if ($name == "place")
{
echo "been here @line(" . __LINE__ . ") Bar::__set('$name', '$value') <br/>";
$result = $this->property2 = $value;
return $result; // may be null
}
return;
}
}
$bar = new Bar;
$bar->name = 'Alice';
$bar->place = 'Wonderland';
echo "done that: '{$bar->name} in {$bar->place}'";
其结果是:
been here @line(22) Foo::__set('name', 'Alice')
been here @line(54) parent::__set('name', 'Alice')
been here @line(59) Bar::__set('place', 'Wonderland')
been here @line(11) Foo::__get('name')
been here @line(38) parent::__get('name')
been here @line(43) Bar::__get('place')
done that: 'Alice in Wonderland'
这是处理继承时重载__get和__set魔术函数的正确答案,但这有开销。这是一个解决办法,但有没有更好的解决办法?
https://stackoverflow.com/questions/26489665
复制