引言
我正在研究关于继承问题的硕士论文,并研究出一些问题 表明存在遗传问题的指标。
如以下示例所示:
示例
public static String getAnimalNoise(Animal animal) {
if (animal instanceof Dog)
return "Woof";
if (animal instanceof Cat)
return "Miau";
return "";
}
如果给定的Animal实例是"Woof"
,则该方法返回String Dog
,如果是"Miau"
,则返回Cat
。空绳子,因为有些动物根本没有噪音。
因此,正确的解决方案应该是使用多态与Animal类中的getNoise
方法。
我已经分析了继承问题的不同指标,并想说是否 其中一些违反了SOLID Principle。
我认为上面的例子违反了:
但我不确定这是否适用于所有人。
我想:
违反原则
SRP违规行为
因为条件语句完全违反 SRP ,因为像开关一样 案例陈述或多个if-else陈述都要考虑多个责任。
存在两种情况,因此更改方法的原因不止一个。
OCP违规行为
因为如果添加新动物,必须在方法中添加新案例 所以方法并不接近修改。
LSP VIOLATION
每个分支执行依赖于动物子类型的不同动作。 我认为违反了 LSP ? 我知道矩形和正方形的例子以及getArea但这些 我认为也适用于违规的例子。
DIP VIOLATION
条件语句具有依赖性,这意味着语句依赖于细节,而不依赖于违反 DIP 的抽象。
问题:
因此,对于给定的例子,问题是否真的违反了给定的原则并且推理是否正确?
答案 0 :(得分:8)
SRP 因为条件语句完全违反了SRP,因为像switch case语句或多个if-else语句一样会考虑多个责任。 它存在两种情况,因此改变方法的原因不止一个。
我非常不同意。 SRP旨在用少量的盐来解释。阅读Uncle Bob's article on it here - 他创造了这个原则。
我引用重要的一些内容:
什么定义了改变的理由?
这个原则是关于人的。
当您编写软件模块时,您希望确保在请求更改时,这些更改只能来自一个人,或者更确切地说,来自一个紧密耦合的人群,代表一个狭义的业务功能。您希望将模块与整个组织的复杂性隔离开来,并设计您的系统,使每个模块负责(响应)仅一个业务功能的需求。
[...]当你想到这个原则时,请记住改变的原因是人。是要求变更的人。而且你不想把这些人或者你自己混淆在一起,将不同人所关心的代码混合在一起。
OCP 因为如果添加新动物,必须在方法中添加新案例,以便方法不会因修改而关闭。
正确。该方法假定一组特定的实现,并且无法在不进行修改的情况下处理新的实现。
LSP 每个分支执行依赖于动物子类型的不同动作。我认为违反了LSP?!
它违反了LSP,但原因不同。如果我要传入长颈鹿,我会得到一个意想不到的结果,一个空字符串。这意味着该方法对于Animal
的任何子类型都不正确。
DIP 条件语句具有依赖性,这意味着语句依赖于细节,而不依赖于违反DIP的抽象。
技术上是正确的,但这只是违反上述其他两个原则的副作用。它并不是问题的核心。
请记住,原则不是规则,因此在解释时不要过于严格/字面意思。实用主义和理解为什么需要一个原则是关键。
答案 1 :(得分:2)
我不同意您的示例代码违反LSP的事实。 LSP定义如下:
设Φ(x)是关于类型T的对象x可证明的属性。对于S类型的对象y,Φ(y)应该为真,其中S是T的子类型。
鉴于Animal的两个推导,即Dog
和Cat
以及您的方法getAnimalNoise
,您不会对具体对象的某些可证明属性做出决策。你的方法是决定应该返回什么样的噪音而不是那些自己的对象。
因此,假设您可以设置动物的腿数。
Animal a = new Animal()
a.setLegFront(2);
a.setLegRear(2);
如果你的Dog
像这样覆盖:
class Dog extends Animal
{
public void setFrontLegs(int legs)
{
this.frontLegs = legs;
this.rearLegs = legs + 2;
}
public void setRearLegs(int legs)
{
// do nothing here for demonstration purposes
}
}
如果您现在有一家工厂退回Animal
Animal createAnimal()
{
return new Dog();
}
Animal a = createAnimal();
a.setFrontLegs(2);
a.setRearLegs(2);
你调用方法setFront/setRearLegs
你期望结果是2和2,但实际上结果是完全不同的,即2和4.所以这个例子与普通的LSP例子紧密结合和矩形。但对我来说,这是一个比你的例子更可靠的违反可证明属性的例子。
我同意你的观点,其他原则也被违反,但对于SRP,我同意@dcastro。