我有类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个,它不多,但仍然是它的重复和继承,在这种情况下不会有重复。
更新
我希望看到解释,我可以用来向任何不同意继承对这种情况不利的人解释。例如,我与一位经验丰富的程序员讨论过,他没有看到使用继承进行代码重用的问题。我刚才说互联网上有很多关于使用组合的内容,但这并不适合这种情况。
例如:
对某些人来说,这不是一个好的理由。他们可以问 - 谁发明了这些规则以及为什么?他们没有通过违反这条规则来解决问题。赞成合成而不是继承。如果两个班级没有"是 一个"关系,那么永远不必使用继承 实现代码重用。从不。
答案 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)
如果MonthTimeCard
和MonthReport
在逻辑上没有相互延伸(例如Dog
和Cat
是Animal
的子类型),那就不太好了无论如何都要在这里使用继承。
除此之外,如果您在多个位置进行相同的验证,您可以引入一个独立的DateValidator
类,并在需要时使用它。
public class DateValidator {
public static boolean validate(final String dateString) {
return ...; // TODO: Validate user input here
}
}