关于oop:php中的多重继承

关于oop:php中的多重继承

Multiple Inheritance in PHP

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

消息--文本消息--------邀请文本消息——电子邮件消息--------邀请邮件消息

这两种类型的invitation*类有很多共同点;我希望有一个共同的父类invitation,它们都将从中继承。不幸的是,他们和他们现在的祖先也有很多共同之处…短信和电子邮件。这里是多重继承的经典愿望。

解决这个问题最简单的方法是什么?

谢谢!


亚历克斯,大多数时候你需要多重继承是一个信号,你的对象结构有点不正确。在你概述的情况下,我认为你的班级责任过于宽泛。如果消息是应用程序业务模型的一部分,则不应考虑呈现输出。相反,您可以分割责任并使用messagedispatcher,它发送使用文本或HTML后端传递的消息。我不知道你的代码,但是让我用这种方式来模拟它:

1
2
3
4
5
6
7
8
9
$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);

通过这种方式,您可以向消息类添加一些专门的内容:

1
2
3
4
5
6
$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还是纯文本发送。

1
2
3
4
5
6
7
8
9
10
// 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/invitationextmessage类中完成,发送算法委托给调度程序。这就是所谓的策略模式,您可以在这里了解更多。


也许你可以用"有-有"的关系来代替"是-一"的关系?邀请可能有消息,但不一定需要"is-a"消息。邀请F.E.可能会得到确认,这与消息模型不匹配。

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


如果我能引用菲尔的话…

PHP, like Java, does not support multiple inheritance.

Coming in PHP 5.4 will be traits which attempt to provide a solution
to this problem.

In the meantime, you would be best to re-think your class design. You
can implement multiple interfaces if you're after an extended API to
your classes.

还有克里斯…

PHP doesn't really support multiple inheritance, but there are some
(somewhat messy) ways to implement it. Check out this URL for some
examples:

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

他们都有有用的链接。迫不及待地想尝试一些特质或者是一些混音…


symfony框架为此提供了一个mixin插件,您可能希望将其签出——即使只是出于想法,如果不使用它的话。

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


我正在使用PHP5.4中的特性来解决这个问题。http://php.net/manual/en/language.oop5.traits.php

这允许使用扩展进行经典继承,但也允许将公共功能和属性放入"特性"中。如手册所述:

Traits is a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies.


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

神奇的方法有哪些?我还没有测试这个解决方案,但是如果您创建了一个多继承类,该怎么办?子类中的受保护变量可以包含要继承的类数组。多接口类中的构造函数可以创建要继承的每个类的实例,并将它们链接到私有属性,例如"ext"。方法可以在"ext"数组中的每个类上使用方法"exists()函数来定位要调用的正确方法。_ get()和uu set可用于定位内部属性,或者如果您的专家具有引用,则可以使子类和继承类的属性成为对同一数据的引用。对象的多重继承对于使用这些对象的代码是透明的。此外,如果需要,内部对象可以直接访问继承的对象,只要用类名索引ext数组。我已经设想过创建这个超级类,但还没有实现它,因为我觉得如果它工作的话,可能会导致开发出各种各样的坏编程习惯。


听起来装饰图案可能是合适的,但如果没有更多的细节,很难说清楚。


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

1)您的消息对象是否只包含消息,如正文、收件人、计划时间?2)您打算如何处理您的邀请对象?与电子邮件相比,是否需要特别处理?3)如果有,有什么特别之处?4)如果是这种情况,为什么邀请的消息类型需要处理不同?5)如果您想发送欢迎信息或OK信息,该怎么办?它们也是新物体吗?

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

例如:我构建的一个系统有一个共享的基本消息对象,它被扩展为短信息、电子邮件和其他消息类型。但是:这些没有进一步扩展-邀请消息只是通过电子邮件类型的消息发送的预定义文本。一个特定的邀请申请将涉及一个邀请的确认和其他要求。毕竟,您所要做的就是将消息X发送给收件人Y,后者本身应该是一个独立的系统。


PHP支持接口。这可能是一个很好的选择,取决于您的用例。


同样的问题,如Java。尝试使用带有抽象函数的接口来解决该问题


在邮件类的正下方开一个邀请类怎么样?

所以层次结构是:

消息---邀请------文本消息------电子邮件

在邀请类中,添加invitationextmessage和invitationemailmessage中的功能。

我知道邀请并不是一种信息,它更像是一种信息的功能。所以我不确定这是不是很好的OO设计。


推荐阅读