在PHP中使用多态时如何避免反射

时间:2019-01-23 06:46:42

标签: php oop reflection polymorphism

我遇到的情况是我有一个“任务”类,可以“进步”

但是,每个任务都有不同的必需参数才能知道如何进行,因此“进度”应该接收不同的参数。

我所做的是确保每个“任务”都实现一个“ ITask”接口,该接口强制实现“进度”方法。 “ prgoress”方法的参数是“ ITaskProgress”界面,它将使我能够为每个任务分配正确的任务进度。

问题是,当我使用它进行进度时,我需要在Task内反映taskProgress,以了解“ taskProgress”内部存在哪些成员/方法,以便我可以使用它进行进度。

我觉得这不是正确的方法,您将如何正确地将各个部分组合在一起?

假定由于必须将任务和任务进度保存在不同的位置,因此它们不能生活在同一班级。

interface ITaskProgress {};
interface ITask
{
    function progress(ITaskProgress $taskProgress);
}
class DoThisTaskPrgoress implements ITaskProgress
{
    public $needThisToProgress;
}

class DoThatTaskProgress implements ITaskProgress
{
    public $needThatToProgress;
    public $alsoNeeded;
}

class DoThisTask implements ITask
{

    function progress(ITaskProgress $taskProgress)
    {
        if ($taskProgress instanceof DoThisTaskPrgoress)
        {
            $taskProgress->needThisToProgress++;
        }
    }
}

class DoThatTask implements ITask
{
    function progress(ITaskProgress $taskProgress)
    {
        if ($taskProgress instanceof DoThatTaskProgress)
        {
            if ($taskProgress->needThatToProgress > $taskProgress->alsoNeeded)
            {
                $taskProgress->needThatToProgress = 0;
            }

        }
    }
}

1 个答案:

答案 0 :(得分:0)

我知道这是一个自以为是的答案,但是就您对我的观点感兴趣而言,我认为您可以相信自己的感受,并应该更坚定自己的感受:

  

我觉得这不是正确的方法,您将如何正确地将各个部分组合在一起?

问题标题也清楚表明您不喜欢使用反射。因此,摆脱思考可能是将事物正确摆放的好方法。

因此,现在您需要分析一个对象,以便可以使用它。通常,这对于对象来说是非常麻烦的,您的情况只是这种情况的另一个例子。

但是为什么这么麻烦?为了使对象受益,它们应该更加抽象。但是,在这种情况下(请不要像其他示例那样将其视为侮辱),您只需要编写非常专业的代码即可使用对象(Tell Don't Ask)。

这有点像是由内而外。与其说任务的进度是实现细节,不如说任务本身需要处理不同类型的进度。

那么如何解决呢?首先,不要做您不想做的事情(仅根据您的问题做您必须做的事,也就是说,如果我理解您的所有事情都正确,可以解决“多态性的障碍“ [您的命名方式]),因此请删除if

class DoThisTask implements ITask
{

    function progress(DoThisTaskPrgoress $taskProgress)
    {
        $taskProgress->needThisToProgress++;
    }
}

class DoThatTask implements ITask
{
    function progress(DoThatTaskProgress $taskProgress)
    {
        if ($taskProgress->needThatToProgress > $taskProgress->alsoNeeded)
        {
            $taskProgress->needThatToProgress = 0;
        }
    }
}

因此,现在将反射(类型检查)移出进度实现会感觉更好。

特定合同现在仅在某些任务进度方法的调用方之间需要注意,以提供正确的具体任务进度参数。

由于PHP在可见性中没有“朋友”的概念,因此在这里键入更具体的任务进度类型(与任务进度界面相比)非常重要,以便可以清楚地知道该进程希望使用哪种特定类型。 (Don't Look for Things)。

这使我们更接近inversion of control,我们在面向对象编程中经常会遇到这种情况。现在很明显,告诉任务进展需要特定的任务进展,一个表示状态的对象作为方法参数注入。

如果这是您选择用来解决总体问题的首要设计,则它还应该指导您找到面向对象设计的育儿模式。例如。看来您需要(至少是一个很小的)抽象工厂,因此所进行的工作都来自一个类族(progress 任务),因此中央工厂可以提供该类。并且可以注入工厂(控制反转),以便在整个应用程序中这一类类可以是“一个”。

然后哪个任务需要进度,然后工厂可以解决,其余代码应该可以正常工作(tm)。