我正在开发一个可重用的库并一直在创建抽象类,因此客户端可以从这些类中扩展。
问题:实际上我有什么理由应该在这里使用抽象类而不是普通类吗?
注意 - 已经决定我不想使用接口,因为我想在我的库中包含实际的默认方法,因此使用它的客户端不必编写代码。
编辑:所以我正在寻找我想不到的任何优势。例如,当升级库时会使用抽象类来减少对客户端代码的影响——在这种情况下我看不到它会不会?
我正在开发一个可重用的库并一直在创建抽象类,因此客户端可以从这些类中扩展。
问题:实际上我有什么理由应该在这里使用抽象类而不是普通类吗?
注意 - 已经决定我不想使用接口,因为我想在我的库中包含实际的默认方法,因此使用它的客户端不必编写代码。
编辑:所以我正在寻找我想不到的任何优势。例如,当升级库时会使用抽象类来减少对客户端代码的影响——在这种情况下我看不到它会不会?
除非您想强制最终用户从您的类继承,否则没有理由使用abstract。
如果您想让您的类可继承且易于扩展,请在您的方法上使用virtual并确保您有可用的受保护构造函数。
抽象类的动机是要求客户覆盖该类。您对类是否应该是抽象的决定主要取决于抽象是否缺少一些只有类的用户才能提供的基本行为。
如果您使用某种模板方法,您通常可以告诉您需要您的类是抽象的,其中“插入此行为中的漏洞”完成了类的逻辑。如果您的类在没有一些用户提供的逻辑的情况下很有用,那么您可能不需要该类是抽象的。
例如,框架通常不能代表其用户在对象状态验证、打印、显示等方面做出决定,它们需要遵从客户端的具体实现。
抽象类和非抽象类之间的区别在于你不能实例化前者,它必须被覆盖。确定基类的实例本身是否有意义完全取决于您。
让我给你看两个案例。一种是抽象类有意义的地方,另一种是没有意义的地方。
public abstract class Animal {
public string Name {get;set;}
}
public class Dog : Animal {
public Bark(){}
}
public class Cat : Animal {
public Meaow(){}
}
在这种情况下,我们有一个Animal
提供Name
属性实现的公共基础。单独实例化 Animal 是没有意义的,因为世界上没有动物只是动物,它们是枯萎的狗或猫或其他东西。
这是一个具有非抽象基础的情况。
class Path {
public Path(IList<Point> points) {
this.Points = new ReadOnlyCollection<Point>(points);
}
public ReadOnlyCollection<Point> Points {get;}
}
class RectanglePath : Path{
public SquarePath (Point origin, int height, int width) :
base(new List<Point>{origin, new Point(origin.X + width, point.Y}, ....){
}
}
这里没有子类化的路径是有意义的,我们可以创建任意形状,但使用子类可能更方便更具体的形状。
听起来您对虚拟方法和抽象类之间的区别有点困惑。除非您确定它本身没有意义,否则您不需要将您的类标记为抽象类。这在您可能在多个类之间共享行为的领域很有用。
在我看来,你只需要一个普通的类和一些虚拟的方法。