如果我有一个抽象类和该类的派生类,我是否正确,根据良好和实际的设计实践,派生类不应该提供额外的公共方法(它们应该只实现抽象类并可选择覆盖父类方法)?
此外,为每个派生类设置不同的构造方法签名是否可以接受?
答案 0 :(得分:5)
就个人而言,我认为两者都没有问题。
关于派生类的额外公共方法:
在许多情况下,这方面的用处有限。当类被转换或设置为对基类的引用时,额外的方法将不可用,这严重限制了这种做法的有用性。话虽如此,这种方法没有什么特别的错误。子类旨在添加特定行为 - 有时,在类层次结构中,子类中存在不适合基类的新行为。如果子类将经常单独使用,那么在方法中建模额外行为似乎是完全合理的。
至于构造函数签名 -
我也没有看到这个问题。子类通常需要将更多信息放入可用状态而不是抽象类。话虽这么说,我通常会确保实现基类中的每个构造函数,并添加子类所需的新参数。
话虽如此:
除非有充分的理由,否则我会避免使用参数少于基类的子类构造函数...为什么我能够在更通用的情况下指定某些内容而不是特定情况?我发现当子类具有与其基类完全不同的构造选项时,通常会感到困惑。
答案 1 :(得分:2)
这是派生类的美妙。
虽然Pen类可能有write()函数,但扩展Pen的RetractablePen类也可能有一个retractPoint()函数。
当你扩展一个类时,它意味着 - 从字面上 - 扩展它的功能。
答案 2 :(得分:2)
总的来说很好。
您要避免使用通用中的特定内容。即。
foreach(Animal a in myFarm.Animals)
{
a.Feed();
// this is a bit grim
if( a is Horse )
{
((Horse)a).CleanStable();
}
}
所以这不是添加公共方法的行为,而是你从中调用它们的行为。
答案 3 :(得分:1)
向派生类添加其他公共方法是完全可以接受的。给他们不同的结构也是完全可以接受的。 (事实上,这很常见。)
答案 4 :(得分:1)
不,添加其他公共方法是完全合理的(有时候设计非常必要)。考虑具有Shape
成员和Location
方法的Size
抽象基类的(完全人为的)情况。例如,当您从Polygon
派生Shape
时,您可能需要添加名为GetNumberOfSides()
的公共方法;但是当你从Circle
派生Shape
时,你不希望这样。
同样地,派生类型可能具有非常不同的构造要求;在定义抽象基类时,不可能知道所有要求可能是什么,因此可以随意使用不同的签名。仅仅因为你的类型将是抽象基类的多态,并不意味着该基类对如何实现该基类中定义的抽象施加了严格的限制;无论你想要什么,你都可以自由地做。
答案 5 :(得分:1)
如果你尊重Liskov substitution principle,你可以做你想做的事。
当然,向派生类添加方法根本不违反原则。
答案 6 :(得分:0)
派生类不应提供额外的公共方法
狗可以做动物不能做的事吗?
此外,为每个派生类设置不同的构造方法签名是否可以接受?
这里没问题。派生类型不需要匹配其兄弟姐妹或父母的构造函数签名。
答案 7 :(得分:0)
不仅可以接受,构造函数通常需要不同。例如,如果我们有一个(不可变的)Rectangle
类并使用(不可变的)Square
扩展它,那么Square的构造函数应该是(暂时使用Java)
public Square(double size)
而Rectangle
的构造函数将是
public Rectangle(double width, double height)
需要发生的是子类构造函数应该调用一些适当的超类构造函数。
对于额外的公共方法,它可能取决于使用。对于Square案例,我不会添加任何额外的方法。但是,在Java中,PrintWriter
有一个子类Writer
其目的是增加一些便利方法。在这种情况下,我认为没关系(Java肯定有一些不好的例子,但我不认为这是其中之一)。我还希望有一些额外的方法可用于容器/子部分类型。
你不应该做的是以违反超类期望的方式改变超类方法。