【问题标题】:Extra public methods in derived classes?派生类中的额外公共方法?
【发布时间】:2010-11-01 13:32:44
【问题描述】:

如果我有一个抽象类和该类的派生类,我是否更正了,根据良好和实用的设计实践,派生类不应该提供额外的公共方法(它们应该只实现抽象类并可选地覆盖父类方法)?

此外,对于每个派生类具有不同的构造函数方法签名是否可以接受?

【问题讨论】:

  • EDIT 仅供参考,我指的是您从工厂构造对象的情况。我认为调用代码,在工厂的情况下,应该知道派生类应该有什么方法。

标签: oop design-patterns public-method


【解决方案1】:

如果你尊重Liskov substitution principle,你可以为所欲为。

当然,给派生类添加方法一点也不违反原则。

【讨论】:

    【解决方案2】:

    这不仅是可以接受的,而且构造函数通常需要不同。例如,如果我们有一个(不可变的)Rectangle 类并用(不可变的)Square 扩展它,Square 的构造函数应该是(暂时使用 Java)

    public Square(double size)
    

    Rectangle 的构造函数是

    public Rectangle(double width, double height)
    

    需要做的是子类构造函数应该调用一些适当的超类构造函数。

    至于额外的公共方法,可能取决于用途。对于 Square 案例,我不会添加任何额外的方法。然而,在 Java 中,Writer 有一个子类 PrintWriter 其目的是添加一些方便的方法。在这种情况下,我认为还可以(Java 肯定有一些不好的例子,但我认为这不是其中之一)。我还希望为容器/子部分类型提供一些额外方法的可能性。

    你不应该做的是以违反超类期望的方式更改超类方法。

    【讨论】:

      【解决方案3】:

      总的来说还不错。

      您要避免在泛型中使用特定。即

      foreach(Animal a in myFarm.Animals)
      {
          a.Feed();
          // this is a bit grim
          if( a is Horse )
          {
             ((Horse)a).CleanStable();
          }
      }
      

      所以这不是添加公共方法的行为,而是你从哪里调用它们。

      【讨论】:

      • 我想要一匹能自己打扫马厩的马!我在哪里可以得到一个? ;)
      • 是的......我知道......我在构建期间写作,所以我没有时间像往常一样迂腐...... :(......它会做。
      【解决方案4】:

      不,添加额外的公共方法是完全合理的(有时在设计上非常必要)。考虑具有Location 成员和Size 方法的Shape 抽象基类的(完全人为的)情况。例如,当您从Shape 派生Polygon 时,您可能希望添加一个名为GetNumberOfSides() 的公共方法,例如;但是当您从Shape 派生Circle 时,您不想拥有它。

      同样,派生类型可能有非常不同的构造要求;在定义抽象基类时,不可能知道所有的要求是什么,所以请随意使用不同的签名。仅仅因为你的派生类型对于抽象基类是多态的,并不意味着该基类对你如何实现该基类中定义的抽象施加了严格的限制。你可以随心所欲地去做。

      【讨论】:

        【解决方案5】:

        这就是派生类的美妙之处。

        虽然 Pen 类可能具有 write() 函数,但扩展 Pen 的 RetractablePen 类也可能具有retractPoint() 函数。

        当你扩展一个类时——字面意思——扩展它的功能。

        【讨论】:

        • 如果你从工厂构造一个对象,那么我不应该有额外的公共方法是对的吗?在工厂的情况下,调用代码不应该知道期望有什么方法吗?
        • 如果您是从工厂构建它,那么您可能正在使用多态性并将该类视为它的父类。在这种情况下,除非您检查 instanceof 并对其进行强制转换,否则您将无法访问子类中定义的方法。
        【解决方案6】:

        我个人认为两者都没有问题。

        至于派生类的额外公共方法:

        在许多情况下,它的用处有限。当类被强制转换或设置为对基类的引用时,额外的方法将不可用,这严重限制了这种做法的实用性。话虽如此,这种方法并没有什么特别的错误。子类旨在添加特定行为 - 有时,在类层次结构中,子类中有不适合基类的新行为。如果子类要经常单独使用,那么在方法中建模额外的行为似乎是完全合理的。

        至于构造函数签名 -

        我也认为这没有问题。子类通常需要比抽象类更多的信息才能进入可用状态。话虽如此,我通常会确保在基类中实现每个构造函数,并添加子类所需的新参数。

        话虽这么说:

        除非有充分的理由,否则我会避免使用参数少于基类的子类构造函数...为什么我能够在更通用的情况下而不是在特定情况下指定一些东西?我发现当子类的构造选项与它们的基类完全不同时,这通常会让人感到困惑。

        【讨论】:

        • 如果你从工厂构造一个对象,那么我不应该有额外的公共方法是对的吗?在工厂的情况下,调用代码不应该知道期望有什么方法吗?
        • 这取决于 - 即使您是从工厂构造的,工厂也需要知道对象的编译时类型(以便调用适当的构造函数)。它可以“知道”额外的参数。不过,在这种情况下,它实际上只取决于场景、如何使用等。
        【解决方案7】:

        派生类不应提供额外的公共方法

        狗能做动物不能做的事吗?

        此外,对于每个派生类具有不同的构造函数方法签名是否可以接受?

        这里没有问题。派生类型不需要匹配其兄弟姐妹或父母的构造函数签名。

        【讨论】:

        • 回答你的问题,是的,狗可以做一些动物不能做的事情......比如吠叫、咬、跑、脱、跳等......蠕虫是动物,(它们'不是植物)-蠕虫不能做任何这些事情......
        【解决方案8】:

        向派生类添加额外的公共方法是完全可以接受的。给他们不同的构造器也是完全可以接受的。 (其实这很常见。)

        【讨论】:

          猜你喜欢
          • 2018-09-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-06
          • 1970-01-01
          • 2020-11-25
          • 1970-01-01
          相关资源
          最近更新 更多