PHP中的多重继承

时间:2020-03-06 14:20:26  来源:igfitidea点击:

我正在寻找一种好的,简洁的方法来解决以下事实:PHP5仍然不支持多重继承。这是类的层次结构:

信息
-文本消息
------- InvitationTextMessage
-Email消息
------- InvitationEmailMessage

两种类型的Invitation *类有很多共同点。我希望有一个共同的父类,邀请函,他们两个都可以继承。不幸的是,他们与当前祖先也有很多共同点……TextMessage和EmailMessage。对多重继承的经典渴望。

解决问题最轻巧的方法是什么?

谢谢!

解决方案

听起来装饰器模式可能是合适的,但是如果没有更多细节很难说。

Symfony框架为此提供了一个mixin插件,我们可能想将其检出-即使只是出于想法,如果不使用它。

"设计模式"的答案是将共享功能抽象为一个单独的组件,并在运行时进行组合。考虑一种将邀请功能抽象为与继承之外的其他方式与Message类相关联的类的方法。

像Java一样的问题。尝试使用具有抽象功能的接口来解决该问题

也许我们可以将" is-a"关系替换为" has-a"关系?邀请可能有一条消息,但不一定需要"是"消息。邀请函可能会被确认,但与Message模型一起使用时效果不佳。

如果我们需要了解更多信息,请搜索"组成与继承"。

PHP确实支持接口。根据用例,这可能是一个不错的选择。

Alex,大多数时候我们需要多重继承是一个信号,表明对象结构有些不正确。在我们概述的情况下,我看到班级职责范围太广了。如果Message是应用程序业务模型的一部分,则它应该不关心呈现输出。相反,我们可以划分责任并使用MessageDispatcher来发送使用文本或者html后端传递的消息。我不知道代码,但让我以这种方式进行模拟:

$m = new Message();
$m->type = 'text/html';
$m->from = 'John Doe <[email protected]>';
$m->to = 'Random Hacker <[email protected]>';
$m->subject = 'Invitation email';
$m->importBody('invitation.html');

$d = new MessageDispatcher();
$d->dispatch($m);

这样,我们可以向Message类添加一些特殊化:

$htmlIM = new InvitationHTMLMessage(); // html type, subject and body configuration in constructor
$textIM = new InvitationTextMessage(); // text type, subject and body configuration in constructor

$d = new MessageDispatcher();
$d->dispatch($htmlIM);
$d->dispatch($textIM);

注意,MessageDispatcher将根据传递的Message对象中的type属性来决定是以HTML还是纯文本形式发送。

// in MessageDispatcher class
public function dispatch(Message $m) {
    if ($m->type == 'text/plain') {
        $this->sendAsText($m);
    } elseif ($m->type == 'text/html') {
        $this->sendAsHTML($m);
    } else {
        throw new Exception("MIME type {$m->type} not supported");
    }
}

概括起来,责任分为两类。消息配置在InvitationHTMLMessage / InvitationTextMessage类中完成,并将发送算法委派给调度程序。这称为策略模式,我们可以在此处阅读更多内容。

我有几个问题要问清楚我们在做什么:

1)消息对象是否仅包含一条消息,例如身体,接收者,时间表?
2)我们打算如何处理邀请对象?与EmailMessage相比,是否需要对其进行特殊处理?
3)如果这样,有什么特别之处?
4)如果是这种情况,为什么对于邀请,消息类型需要进行不同的处理?
5)如果要发送欢迎消息或者OK消息怎么办?它们也是新物体吗?

听起来确实好像我们正在尝试将太多功能组合到一组对象中,而这些对象仅应与保留消息内容有关,而不应与如何处理消息内容有关。对我来说,邀请或者标准消息没有区别。如果邀请需要特殊处理,则意味着应用程序逻辑而不是消息类型。

例如:我构建的系统具有一个共享的基本消息对象,该对象已扩展为SMS,电子邮件和其他消息类型。但是:这些消息没有进一步扩展,邀请消息只是预定义的文本,可以通过电子邮件类型的消息发送。一个特定的邀请应用程序将与邀请的验证和其他要求有关。毕竟,我们要做的就是将消息X发送给收件人Y,该收件人本身应该是一个离散系统。

这既是一个问题,也是一个解决方案。

神奇的_call(),_ get()和__set()方法呢?我尚未测试此解决方案,但是如果我们创建multiInherit类,该怎么办。子类中的受保护变量可以包含要继承的类的数组。多接口类中的构造函数可以创建被继承的每个类的实例,并将它们链接到私有属性,例如_ext。 __call()方法可以在_ext数组中的每个类上使用method_exists()函数来定位要调用的正确方法。 __get()和__set可用于定位内部属性,或者,如果专家具有引用,则可以使子类的属性和继承的类成为对同一数据的引用。对象的多重继承对于使用这些对象的代码而言是透明的。同样,只要_ext数组通过类名索引,内部对象就可以直接访问继承的对象。我已经设想过创建这个超类,但还没有实现它,因为我认为如果它能起作用,可能会导致养成各种不良的编程习惯。