覆盖特征方法时检测递归
Detect recursion when overridding trait methods
两个库分别提供了一个特性,一种覆盖默认基础 class 方法的方法。
// This is a Framework base class
class Model {
function getAttribute($key) {
return "Model->$key";
}
}
// This is a trait from library A which provides extra stuff
trait HasUuid {
function getAttribute($key) {
if ($key==='uuid') return "HasUuid->$key";
return parent::getAttribute($key);
}
}
// This is a trait from library B which provides extra stuff
trait HasQuantity {
function getAttribute($key) {
if ($key==='quantity') return "HasQuantity->$key";
return parent::getAttribute($key);
}
}
现在,我的应用程序中有一个 class 继承自 Model
并且需要使用这两个特征。
PHP 允许为特性函数设置别名,以解决库之间的命名冲突。所以这就是我最终得到的:
class Product extends Model {
use HasUuid { getAttribute as getHasUuidAttribute; }
use HasQuantity { getAttribute as getHasQuantityAttribute; }
function getAttribute($key) {
// Framework default value to use as fallback
$parentValue = parent::getAttribute($key);
$overrides = ['getHasUuidAttribute', 'getHasQuantityAttribute',];
foreach ($overrides as $override)
{
$overriddenValue = $this->$override($key);
// A trait has some better value than the fallback
if ($overriddenValue !== $parentValue) return $overriddenValue;
}
// Nothing better, use fallback from framework
return $parentValue;
}
}
我们最终遇到了一个递归问题:当调用重写的特征方法时,它们引用了 parent::getAttribute
方法,该方法触发了对 Product::getAttribute
的另一个调用,无限递归。
我们如何通过保持对两个特征特征的访问来解决这个递归问题?
当然,由于每个特征都来自一个库,我无法更改它们的代码。
您可以利用 private
关键字将它们设为私有。
class Product extends Model {
use HasUuid { getAttribute as private getHasUuidAttribute; }
use HasQuantity { getAttribute as private getHasQuantityAttribute; }
function getAttribute($key) {
// Framework default value to use as fallback
$parentValue = parent::getAttribute($key);
$overrides = ['getHasUuidAttribute', 'getHasQuantityAttribute',];
foreach ($overrides as $override)
{
$overriddenValue = $this->$override($key);
// A trait has some better value than the fallback
if ($overriddenValue !== $parentValue) return $overriddenValue;
}
// Nothing better, use fallback from framework
return $parentValue;
}
}
希望对您有所帮助。
两个库分别提供了一个特性,一种覆盖默认基础 class 方法的方法。
// This is a Framework base class
class Model {
function getAttribute($key) {
return "Model->$key";
}
}
// This is a trait from library A which provides extra stuff
trait HasUuid {
function getAttribute($key) {
if ($key==='uuid') return "HasUuid->$key";
return parent::getAttribute($key);
}
}
// This is a trait from library B which provides extra stuff
trait HasQuantity {
function getAttribute($key) {
if ($key==='quantity') return "HasQuantity->$key";
return parent::getAttribute($key);
}
}
现在,我的应用程序中有一个 class 继承自 Model
并且需要使用这两个特征。
PHP 允许为特性函数设置别名,以解决库之间的命名冲突。所以这就是我最终得到的:
class Product extends Model {
use HasUuid { getAttribute as getHasUuidAttribute; }
use HasQuantity { getAttribute as getHasQuantityAttribute; }
function getAttribute($key) {
// Framework default value to use as fallback
$parentValue = parent::getAttribute($key);
$overrides = ['getHasUuidAttribute', 'getHasQuantityAttribute',];
foreach ($overrides as $override)
{
$overriddenValue = $this->$override($key);
// A trait has some better value than the fallback
if ($overriddenValue !== $parentValue) return $overriddenValue;
}
// Nothing better, use fallback from framework
return $parentValue;
}
}
我们最终遇到了一个递归问题:当调用重写的特征方法时,它们引用了 parent::getAttribute
方法,该方法触发了对 Product::getAttribute
的另一个调用,无限递归。
我们如何通过保持对两个特征特征的访问来解决这个递归问题?
当然,由于每个特征都来自一个库,我无法更改它们的代码。
您可以利用 private
关键字将它们设为私有。
class Product extends Model {
use HasUuid { getAttribute as private getHasUuidAttribute; }
use HasQuantity { getAttribute as private getHasQuantityAttribute; }
function getAttribute($key) {
// Framework default value to use as fallback
$parentValue = parent::getAttribute($key);
$overrides = ['getHasUuidAttribute', 'getHasQuantityAttribute',];
foreach ($overrides as $override)
{
$overriddenValue = $this->$override($key);
// A trait has some better value than the fallback
if ($overriddenValue !== $parentValue) return $overriddenValue;
}
// Nothing better, use fallback from framework
return $parentValue;
}
}
希望对您有所帮助。