假设我们在\Base\Form\
命名空间中有两个类:
class Field { protected $name; protected $value; } class DropdownField extends Field { protected $options = []; // with functions like setOptions(), addOption(), removeOption() etc. }
现在,在另一个命名空间中,存在一个扩展的类Field
,它具有一个附加'layout_position'
属性:
namespace Integrations; class IntegrationsField extends \Base\Form\Field { const LAYOUT_POSITION_LEFT = 'left'; const LAYOUT_POSITION_RIGHT = 'right'; protected $layoutPosition = self::LAYOUT_POSITION_LEFT; }
现在,您可能会看到这一个即将到来,但如果IntegrationsField
这也可以是下拉列表:
namespace Integrations; class IntegrationsDropdownField extends \Base\Form\DropdownField {}
当然,这个也应该有$layoutPosition
,应该继承IntegrationsField
,但由于我们不能扩展两个类,这里最好的解决方案是什么?
PHP不支持多重继承.但是,您可以使用特征来重写逻辑,以(模拟)模拟它.
class Field { protected $name; protected $value; } trait Dropdown { protected $options = []; // with functions like setOptions(), addOption(), removeOption() etc. } interface IntegrationPositions { const LAYOUT_POSITION_LEFT = 'left'; const LAYOUT_POSITION_RIGHT = 'right'; } trait Integration { protected $layoutPosition = IntegrationPositions::LAYOUT_POSITION_LEFT; } class DropdownField extends Field { use Dropdown; } class IntegrationField extends Field { use Integration; } class DropdownIntegrationField extends Field { use Integration,Dropdown; }
更新:由于@Adambean注意到traits不能有常量.因此,我使用枚举更新了示例.
如果必须声明一个特征内部的枚举,那就觉得很奇怪,但据我所知,PHP似乎不允许任何其他机制实现这一点,我对任何其他想法持开放态度.