Oop 违反了哪些坚实的原则?

Oop 违反了哪些坚实的原则?,oop,inheritance,solid-principles,design-principles,Oop,Inheritance,Solid Principles,Design Principles,导言 我在写关于继承问题的硕士论文,并得出一些结论 指示存在继承问题的指示器 如以下示例所示: 示例 如果给定的动物实例是狗,则该方法返回字符串“Woof”;如果是猫,则返回字符串“Miau”。空字符串,因为有些动物根本不发出任何声音 因此,正确的解决方案应该是在动物类中使用多态性和getNoise方法 我分析了遗传问题的不同指标,想说 他们中的一些人违反了法律 我认为上面的例子违反了: 单一责任原则(SRP) 打开/关闭原则(OCP) Liskov替代原理(LSP) 依赖倒置原则(DIP)

导言


我在写关于继承问题的硕士论文,并得出一些结论 指示存在继承问题的指示器

如以下示例所示:

示例


如果给定的动物实例是
狗,则该方法返回字符串
“Woof”
;如果是
猫,则返回字符串
“Miau”
。空字符串,因为有些动物根本不发出任何声音

因此,正确的解决方案应该是在动物类中使用多态性和
getNoise
方法

我分析了遗传问题的不同指标,想说 他们中的一些人违反了法律

我认为上面的例子违反了:

  • 单一责任原则(SRP)
  • 打开/关闭原则(OCP)
  • Liskov替代原理(LSP)
  • 依赖倒置原则(DIP)
  • 但我不确定这是否对所有人都是真的

    我想:

    违反原则


    SRP违规

    因为条件语句完全违反了SRP,因为 case语句或一个以上的if语句被认为是一个以上的责任。 存在两种情况,因此有不止一个原因需要更改方法

    OCP违规

    因为如果一个新的动物被添加,一个新的案例必须被添加到方法中 因此,该方法不适合修改

    LSP违规

    每个分支根据动物子类型执行不同的操作。 我认为这违反了LSP?! 我知道矩形、正方形和getArea的例子,但是这些 我认为这个例子也适用于违规行为

    倾斜破坏

    条件语句具有依赖性,这意味着语句依赖于细节,而不是违反DIP的抽象

    问题:


    所以问题是,对于给定的例子,给定的原则是否真的被违反了,推理是否正确

    <强> SRP,因为条件语句都违反SRP,因为类似于Switter case语句,或者不止一个if if语句被认为不止一个责任。 存在两种情况,因此有不止一个原因需要更改方法

    我强烈反对。对SRP的解释要有一点保留。他创造了这个原则

    我将引用一些重要的内容:

    什么定义了改变的理由

    这个原则是关于人的

    在编写软件模块时,您希望确保在请求更改时,这些更改只能来自单个人员,或者更确切地说,来自表示单个狭义定义的业务功能的单个紧密耦合的人员组。您希望将您的模块从整个组织的复杂性中分离出来,并设计您的系统,使每个模块只负责(响应)该业务功能的需求

    […]当你思考这个原则时,请记住,改变的原因是人。是人们要求改变。你也不想混淆那些人,或者你自己,把许多不同的人出于不同的原因所关心的代码混在一起


    OCP因为如果添加了新动物,则必须在方法中添加新病例,因此该方法不适合修改

    对。该方法假定有一组特定的实现,如果不进行修改,将无法处理新的实现


    LSP每个分支根据动物子类型执行不同的操作。我认为这违反了LSP

    它违反了LSP,但原因不同。如果我传入一只长颈鹿,我会得到一个意想不到的结果,一个空字符串。这意味着该方法对于
    动物的任何子类型都是不正确的


    DIP条件语句具有依赖性,这意味着这些语句依赖于细节,而不是违反DIP的抽象

    从技术上讲是正确的,但这只是违反上述其他两个原则的副作用。这并不是问题的核心



    记住,原则不是规则,所以在解释它们时不要太严格/字面化。实用主义和理解为什么需要原则是关键。

    我不同意您的示例代码违反LSP这一事实。LSP的定义如下:

    设Φ(x)是关于类型T的对象x可证明的属性。那么Φ(y)对于类型S的对象y应为真,其中S是T的子类型

    考虑到来自动物的两个派生,即
    ,以及您的方法
    getAnimalNoise
    ,您没有对具体对象的某些可证明属性做出决定。您的方法是决定应该返回什么样的噪声,而不是对象本身

    让我们想象一下,你可以设置一只动物的腿数

    Animal a = new Animal()
    a.setLegFront(2);
    a.setLegRear(2);
    
    如果你的
    像这样覆盖了它:

     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 createAnimal()
    {
       return new Dog();
    }
    Animal a = createAnimal();
    a.setFrontLegs(2);
    a.setRearLegs(2);
    
    调用方法setFront/setRearLegs,期望结果是2和2,但实际上结果完全不同,即2和4。因此,这个例子与常见的LSP例子紧密相连,有正方形和矩形。但对我来说,这是一个比你的例子更准确的违反可证明属性的例子

    其他原则的最新情况
    我同意你的观点,其他原则也被违反,但对于SRP,我同意@dcastro。

    我要添加DIP:该方法应该依赖于
    MakesNoiseInterface
    ,而不是具体的类。@deceze不需要接口,抽象已经存在:Animal createAnimal() { return new Dog(); } Animal a = createAnimal(); a.setFrontLegs(2); a.setRearLegs(2);