C# ';抽象类';与';普通班';对于可重用库

C# ';抽象类';与';普通班';对于可重用库,c#,.net,abstract-class,base-class,C#,.net,Abstract Class,Base Class,我正在开发一个可重用的库,并一直在创建抽象类,因此客户端可以从这些抽象类进行扩展 问题:有什么理由我应该在这里使用抽象类而不是普通类吗? 注意-我已经决定不使用接口,因为我希望在我的库中包含实际的默认方法,这样使用它的客户端就不必编写代码 编辑:所以我在寻找我想不到的任何优势。例如,当升级库时,抽象类的使用会减少对客户机代码的影响-我看不出在这种情况下会不会 抽象类和非抽象类之间的区别在于不能实例化前者,必须重写前者。实际上,由您来决定基类实例本身是否有意义 让我给你看两个箱子。一个是抽象类有意

我正在开发一个可重用的库,并一直在创建抽象类,因此客户端可以从这些抽象类进行扩展

问题:有什么理由我应该在这里使用抽象类而不是普通类吗?

注意-我已经决定不使用接口,因为我希望在我的库中包含实际的默认方法,这样使用它的客户端就不必编写代码


编辑:所以我在寻找我想不到的任何优势。例如,当升级库时,抽象类的使用会减少对客户机代码的影响-我看不出在这种情况下会不会

抽象类和非抽象类之间的区别在于不能实例化前者,必须重写前者。实际上,由您来决定基类实例本身是否有意义

让我给你看两个箱子。一个是抽象类有意义的地方,另一个是抽象类没有意义的地方

public abstract class Animal {
  public string Name {get;set;}
}

public class Dog : Animal {
  public Bark(){}
}

public class Cat : Animal {
  public Meaow(){}
}
在这个场景中,我们有一个公共的基础
Animal
,它提供了
Name
属性的实现。将动物本身实例化是没有意义的,因为世界上没有任何动物只是动物,它们是枯萎的狗或猫或其他东西

在这种情况下,有一个非抽象的基础是有意义的

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}, ....){

  }
}
类路径{
公共路径(IList点){
this.Points=新的只读集合(点);
}
公共只读集合点{get;}
}
类矩形路径:路径{
公共方形路径(点原点、整数高度、整数宽度):
基本(新列表{原点,新点(原点.X+宽度,点.Y},…){
}
}

在这里,没有子类化的路径是有意义的,我们可以创建任意形状,但是对于更具体的形状使用子类可能更方便。

除非您想强制最终用户从类继承,否则应该没有理由使用抽象


如果要使类具有可继承性和易于扩展性,请在方法上使用virtual,并确保有可用的受保护构造函数。

听起来您对虚拟方法和抽象类之间的区别有点困惑。除非确定类不是抽象类,否则不需要将类标记为抽象类这在多个类之间可能存在共享行为的领域非常有用


在我看来,您只需要一个常规类和一些虚拟方法。

抽象类的动机是要求客户机重写该类。您对该类是否应为抽象类的决定主要取决于抽象类是否缺少一些只有该类的用户才能执行的基本行为供应

如果您使用某种模板方法,您通常可以告诉您需要抽象类,其中“插入此行为中的漏洞”完成了类的逻辑。如果您的类在没有用户提供的逻辑的情况下很有用,则您可能不需要抽象类


例如,框架通常不能代表其用户在对象状态验证、打印、显示等方面做出决策,它们需要遵从客户机的具体实现。

由于无法实例化抽象类,因此将类抽象化将迫使客户机在n为了使用它们。一般来说,通过继承进行扩展比使用带有组合和事件处理程序的库更困难。至于抽象类与接口,您可以通过使用接口的扩展方法来绕过“默认”方法的问题,这种方法有时更干净。我想知道我给的抽象类是否缺点-例如,当升级库时,这会减少对客户端代码的影响-我看不出在这种情况下会有什么影响不?不是真的。它不会改变耦合级别-即,在这两种情况下,您都需要从基类继承。升级潜力取决于库设计,而不是类是否抽象。我正在寻找一个我想不出有什么优点。例如,当升级库时,使用抽象类可以减少对客户端代码的影响-我看不出在这种情况下会有什么好处。没有多少。即使您不将其标记为虚拟,使用库的程序员也可以用“new”构造一个方法关键字来覆盖您的方法。将您的方法标记为虚拟方法可以使消费者不需要使用“新”关键字来覆盖它。换句话说,它更自然。使用
new
关键字从来不会导致覆盖。这就是重点。它可以让您盗取名称供自己使用,但不存在多态性,这是覆盖的一个基本部分。是的,您在技术上是正确的。然而,从语义上讲,有什么区别吗n在这两种情况下,您都希望用自己的功能替换现有的功能。我本应该说“替换”而不是“覆盖”,但这个概念适用。很难选择-但这个答案提到了虚拟和公共构造函数建议,听起来不错的建议我必须将“公共”改为“受保护”(这是技术上更正确的术语)框架指南指出,您应该至少提供一个抽象类或接口的具体实现,作为类真正有意义的“概念证明”。