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

信息
- 短信
-------- 邀请短信
-- 邮件留言
-------- 邀请邮件留言

两种类型的邀请*课程有很多共同点;我希望有一个共同的父类 Invitation,它们都可以继承它。不幸的是,他们与现在的祖先也有很多共同点……文本消息和电子邮件消息。这里是多重继承的经典愿望。

解决该问题的最轻量级方法是什么?

谢谢!

有帮助吗?

解决方案

Alex,大多数时候,您需要多重继承,这表明您的对象结构有些不正确。在你概述的情况下,我发现你的阶级责任太广泛了。如果消息是应用程序业务模型的一部分,则它不应该关心渲染输出。相反,您可以分割责任并使用 MessageDispatcher 来发送使用文本或 html 后端传递的消息。我不知道你的代码,但让我这样模拟一下:

$m = new Message();
$m->type = 'text/html';
$m->from = 'John Doe <jdoe@yahoo.com>';
$m->to = 'Random Hacker <rh@gmail.com>';
$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 将根据以下情况决定是否以 HTML 或纯文本形式发送 type 已传递 Message 对象中的属性。

// 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 类中完成,发送算法委托给调度程序。这称为策略模式,您可以阅读更多内容 这里.

其他提示

也许您可以将“is-a”关系替换为“has-a”关系?邀请可能有一条消息,但它不一定需要“是一条”消息。邀请函可能会被确认,这与 Message 模型不能很好地配合。

搜索“构图与构图”如果您需要了解更多信息,请参阅“继承”。

如果我能引用菲尔的话 这个线程...

PHP 和 Java 一样,不支持多重继承。

PHP 5.4 中将会出现 特质 试图为此问题提供解决方案。

与此同时,你最好重新考虑你的课程设计。如果您是在课程中进行扩展的API,则可以实现多个接口。

还有克里斯……

PHP并不真正支持多个继承,但是有一些(某种混乱)实施它的方法。查看此URL以获取一些示例:

http://www.jasny.net/articles/how-i-php-multiple-inheritance/

认为他们都有有用的联系。迫不及待地想尝试一些特性或者一些混合......

Symfony 框架有一个 mixin 插件用于此, ,你可能想看看它——即使只是为了想法,如果不是为了使用它。

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

我使用 PHP 5.4 中的特征来解决这个问题。http://php.net/manual/en/language.oop5.traits.php

这允许使用扩展进行经典继承,但也可以将通用功能和属性放入“特征”中。正如手册所说:

Traits 是单继承语言(例如 PHP)中代码重用的机制。Trait 旨在通过使开发人员能够在不同类层次结构中的多个独立类中自由地重用方法集来减少单一继承的一些限制。

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

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

神奇的_呢?称呼(),_get()、__set() 方法?我还没有测试这个解决方案,但是如果你创建一个 multiInherit 类怎么办?子类中的受保护变量可以包含要继承的类的数组。多接口类中的构造函数可以创建每个被继承的类的实例,并将它们链接到私有属性,例如 _ext。__call() 方法可以在 _ext 数组中的每个类上使用 method_exists() 函数来查找要调用的正确方法。__get() 和 __set 可用于定位内部属性,或者如果您是具有引用的专家,您可以使子类和继承类的属性成为对相同数据的引用。对象的多重继承对于使用这些对象的代码来说是透明的。此外,只要 _ext 数组按类名索引,内部对象就可以根据需要直接访问继承的对象。我曾设想创建这个超类,但尚未实现它,因为我觉得如果它有效,可能会导致养成一些不同的不良编程习惯。

我有几个问题要问以澄清您在做什么:

1) 您的留言是否反对 只是 包含一条消息,例如正文、收件人、安排时间?2) 您打算如何处理您的 Invitation 对象?与 EmailMessage 相比,它是否需要特殊处理?3)如果是的话,它有什么特别之处?4) 如果是这样的话,为什么邀请的消息类型需要进行不同的处理?5) 如果您想发送欢迎消息或 OK 消息怎么办?它们也是新对象吗?

听起来确实像是您正在尝试将太多的功能组合到一组对象中,而这些对象只应该关心保存消息内容,而不是如何处理它。你看,对我来说,邀请和标准消息没有区别。如果邀请需要特殊处理,那么这意味着应用程序逻辑而不是消息类型。

例如:我构建的系统有一个共享的基本消息对象,该对象已扩展到短信、电子邮件和其他消息类型。然而:这些没有进一步扩展 - 邀请消息只是通过电子邮件类型的消息发送的预定义文本。特定的邀请应用程序将涉及邀请的验证和其他要求。毕竟,您要做的就是将消息 X 发送给接收者 Y,接收者 Y 本身应该是一个离散系统。

和Java一样的问题。尝试使用具有抽象函数的接口来解决该问题

PHP 确实支持接口。这可能是一个不错的选择,具体取决于您的用例。

在 Message 类下面添加一个 Invitation 类怎么样?

所以层次结构是:

信息
--- 邀请函
- - - 短信
------ 邮件留言

在 Invitation 类中,添加 InvitationTextMessage 和 InvitationEmailMessage 中的功能。

我知道邀请并不是真正的消息类型,它更多的是消息的功能。所以我不确定这是否是好的面向对象设计。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top