如何在不使用继承的情况下使用私有变量设置减少代码重复?

时间:2015-09-17 09:59:52

标签: php perl oop code-duplication

我有类MonthTimeCard和MonthReport。他们使用相同的输入字段来选择月份,因此验证是相同的,初始化是相同的。

class MonthTimeCard {

private function setPrivateVarsByUserInput()
    {
        $this->month_from_input = '2015-09';

        $this->date_from = '2015-09-01';
        $this->date_to = '2015-09-30';

        // lets say those 3 values are formated, validated and returned as array from MonthUserInput class.
        // but I have to repeat code in my both classes to initialize them
        // I could have one liner like $this->data = $this->monthUserInput->getInput();
        // but current class code will need to call $this->data->[variable] everywhere - not looking very nice,
        // because ->data is not usefull here, just extra characters.
    }

}

Class MonthReport {
    ... same initialisation
}

我现在只是对它们进行了硬编码,但是你知道赋值将来自MonthUserInput类的返回数组,它将进行验证。只有一个用户输入字段可以像2015-09' 2015-09'和MonthUserInput类将添加月的第一天和最后一天。

如果我使用继承,我可以避免这种情况,但我已经阅读了应该避免的,有些人甚至说它应该从OOP中删除。

http://blogs.perl.org/users/sid_burn/2014/03/inheritance-is-bad-code-reuse-part-1.html

通过继承,我只是在父类中验证和设置用户输入,因此没有重复。

我现在应该怎么做?当然,在这个例子中它只有3个变量,我计划有5个,它不多,但仍然是它的重复和继承,在这种情况下不会有重复。

更新

我希望看到解释,我可以用来向任何不同意继承对这种情况不利的人解释。例如,我与一位经验丰富的程序员讨论过,他没有看到使用继承进行代码重用的问题。我刚才说互联网上有很多关于使用组合的内容,但这并不适合这种情况。

例如:

  

赞成合成而不是继承。如果两个班级没有"是   一个"关系,那么永远不必使用继承   实现代码重用。从不。

对某些人来说,这不是一个好的理由。他们可以问 - 谁发明了这些规则以及为什么?他们没有通过违反这条规则来解决问题。

2 个答案:

答案 0 :(得分:1)

继承是一个功能强大的工具,可以实现代码重用,但是它带来了潜在的问题,应该适当使用。因为子类依赖在超类实现上,继承打破了封装并且可能使代码更脆弱且难以维护。

当确实存在" IS A"时,实现仅使用继承 的纪律。关系,例如。一个PreferredClient是一个客户......或者......一个MountainBike是一个自行车。如果您正在设计一个与预期的超类没有实现IS A关系的类,那么就不要使用继承。

通过使用组合而不是继承,您可以实现类似程度的代码重用。不是创建子类,而是将预期的超类合并为类的属性。这允许您将方法调用委托给包含的实例并实现代码重用。

对于您的代码示例,建议的代码分解可能是这样的:

class MonthTimeCard {

    Month myMonth;

    MonthTimeCard(Month month) { myMonth = month; }

    private function setPrivateVarsByUserInput()  {
        // calls to myMonth
    }

}

Class MonthReport {
    // calls to myMonth
}

Class Month {
    $this->month_from_input = ...

    $this->date_from = ...
    $this->date_to = ...
}

答案 1 :(得分:0)

如果MonthTimeCardMonthReport在逻辑上没有相互延伸(例如DogCatAnimal的子类型),那就不太好了无论如何都要在这里使用继承。

除此之外,如果您在多个位置进行相同的验证,您可以引入一个独立的DateValidator类,并在需要时使用它。

public class DateValidator {

  public static boolean validate(final String dateString) {
    return ...; // TODO: Validate user input here
  }

}