在PHP中重载属性和方法 - 原因是什么?

问题描述:

使用重载仅用于可爱的功能命名原因是一个好主意吗? :)在PHP中重载属性和方法 - 原因是什么?

例如:

echo $store->product->getPrice($currency);

  • product将调用__get然后__getObject(“产品”)来完成玛姬东西,并返回该用户正在观看作为对象的当前产物(它是实例化,如果是第一次调用)

echo $store->product('dog')->getPrice($currency);

  • 这里product将调用__call,然后__callObject( '产品',...)...


没有超载另一种方法是:

if(!$store->product) 
    $store->product = new Product(); 

echo $store->product->getPrice($currency); 

$product = new Product('dog'); 
echo $product->getPrice($currency); 

我真的很喜欢重载,因为我可以为我的课程获得很好的API。但缺点是重载的东西比直接调用属性/方法要慢15倍。

可以像这样使用重载吗?

在我当前的应用程序中,我没有调用超过1000次的超载成员。这应该不会对性能产生太大影响。也许额外0.1s,考虑到一个网站通常生成0.5 - 1s不是很多

+0

在这段代码的性能开销似乎并不显著。但我通常害怕使用大量的__call和__get方法(假设你将在整个软件中使用它) – TFennis 2012-01-03 12:13:31

+1

如果你的整个API依赖于Magic Methods,那么性能影响可能很大,并且有一个很多人不喜欢魔法代码,因为它并不明显。 – Gordon 2012-01-03 12:18:36

的是它使用重载全权可爱的功能命名的原因是一个好主意? :)

不,我的意思是,这取决于。 :)让我们有些迷死和可爱添加到我们的编程生涯:

$ordinary = new stdClass(); 
$ordinary->Caption = 'Hello'; 

class Awesome 
{ 
    private $ordinary; 
    public function __construct($ordinary) { 
     $this->ordinary = (array) $ordinary; 
    } 
    public function __get($name) { 
     $value = ''; 
     return $this->ordinary[$name]; 
    } 
} 

class Lovely extends Awesome 
{ 
    public function __get($name) 
    { 
     return '<3 ' . parent::__get($name) . ' <3'; 
    } 
} 

我必须承认,例如可能是一个比最高位,但显示了一些。

首先,假设API是针对一个类的。所以它从一个非常普通的stdClass开始。

什么例子则说明的是,那些神奇的功能,可用于超载装饰东西。可以,但不可以。见真棒API,它本身只是真棒:

$awesome = new Awesome($ordinary); 

echo $awesome->Caption, "\n"; # This caption is just awesome by itself! 
# Hello 

然后看到更可爱的API例如:

$lovely = new Lovely($ordinary); 

echo $lovely->Caption, "\n"; # This caption is lovely, hughs and kisses everyone! 
# <3 Hello <3 

因此,在这个例子中,它是Lovely一个好主意,但它是无用的Awesome,因为Awesome实际上是更容易获得:

$awesome = $ordinary; 

这使我想到了一点,即在API中重载可以ONL y在某个特定点上是有用的。正如Lovely所示,它可以用来装饰另一个(没有多少指定的对象),但它也表明这只是一次性的:Lovely已经需要知道如何调用Awesome以利用它的功能(现在不是魔术再)__get方法:

public function __get($name) 
    { 
     return '<3 ' . parent::__get($name) . ' <3'; 
    } 

当你现在考虑Awesome是你的API,你可以看到,它阻止本身能够被从想要利用它的另一coderette容易过载。

因此,在具体的代码中,重载可以很好,API不应该阻止这种情况。但是,当API本身过载时,事情可能变得困难。

不仅对于编码,添加动态/魔法还会使事情难以调试。因此,请更好地保持您创建的API的清晰,并提供更具体的接口,然后只需[]->。你可以给的东西具体名称和行之有效;)

而且它更可爱那么:

echo $store->getObject('product')->getPrice($currency); 

重载的缺点是,你必须自己描述“漂亮的API”,因为文档工具不能理解,什么你在你的方法里面做。还有一点是,它通常“太过神奇”:你让你的代码更难以理解你实现的更多魔法。

另一方面,我没有看到您的替代方案有任何问题。它在我眼中更清洁。

旁注:只要你没有实现魔术方法,在你自己的方法开始时避免使用双下划线。

收益来源于坚持面向对象的设计原则。第一个示例允许通过从工厂生成产品对象来实现松耦合。欲了解更多关于面向对象的设计原则,见S.O.L.I.D. and G.R.A.S.P.