我知道抽象类是一种特殊的类,不能被实例化。抽象类只能被子类化(继承)。换句话说,它只允许其他类继承它,但不能实例化它。优点是它可以为所有子类强制执行某些层次结构。简单来说,它是一种强制所有子类遵循相同层次结构或标准的契约。
我也知道接口不是类。它是一个由“接口”一词定义的实体。接口没有实现;它只有签名,或者换句话说,只有方法的定义,没有主体。作为与抽象类的相似之处之一,它是一个契约,用于定义所有子类的层次结构,或者定义特定的方法集及其参数。它们之间的主要区别在于,一个类可以实现多个接口,但只能继承一个抽象类。由于C#不支持多重继承,因此使用接口来实现多重继承。
当我们创建接口时,我们基本上是在创建一组没有任何必须由已实现的类覆盖的实现的方法。优点是它提供了一种使一个类成为两个类的一部分的方法:一个来自继承层次结构,一个来自接口。
当我们创建抽象类时,我们正在创建一个基类,该基类可能具有一个或多个已完成的方法,但至少有一个或多个方法未完成并声明为抽象。如果抽象类的所有方法都不完整,那么它与接口相同。
BUT
BUT
BUT
我注意到我们将会有C# 8.0 中的默认接口方法
也许我这么问是因为我只有 1-2 年的编程经验,但是现在抽象类和接口之间的主要区别是什么?
我知道我们不能在界面中创建状态,这只是它们之间的一个区别吗?
概念性的
首先,类和接口之间存在概念上的区别。
- 类应该描述“是”关系。例如。法拉利是一辆汽车
- 接口应该描述类型的契约。例如。汽车有方向盘。
目前,抽象类有时用于代码重用,即使没有“是”关系。这会污染 OO 设计。例如。FerrariClass
继承自CarWithSteeringWheel
Benefits
- 因此,从上面来看,您可以重用代码,而无需引入(概念上错误的)抽象类。
- 您可以从多个接口继承,而抽象类只能单继承
- C# 中接口存在协变和逆变,而类则不存在
- 实现接口更容易,因为某些方法有默认实现。这可以为接口的实现者节省大量工作,但用户不会看到差异:)
- 但对我来说最重要的是(因为我是库维护者),您可以向接口添加新方法,而无需进行重大更改!在 C# 8 之前,如果接口是公开发布的,则应该对其进行修复。因为改变接口可能会破坏很多。
记录器接口
这个例子展示了一些好处。
您可以如下描述(过于简化的)记录器界面:
interface ILogger
{
void LogWarning(string message);
void LogError(string message);
void Log(LogLevel level, string message);
}
然后该界面的用户可以使用以下方式轻松记录警告和错误LogWarning
and LogError
。但缺点是实现者必须实现所有方法。
一个更好的默认界面是:
interface ILogger
{
void LogWarning(string message) => Log(LogLevel.Warning, message);
void LogError(string message) => Log(LogLevel.Error, message);
void Log(LogLevel level, string message);
}
现在用户仍然可以使用所有方法,但实现者只需要实现Log
。还有,他could实施LogWarning
and LogError
.
另外,将来您可能希望添加日志级别“灾难性”。在 C#8 之前,您无法添加该方法LogCatastrophic
到 ILogger,而不破坏所有当前的实现。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)