默认接口方法。抽象类和接口之间现在有什么深刻的、有意义的区别?

2023-11-30

我知道抽象类是一种特殊的类,不能被实例化。抽象类只能被子类化(继承)。换句话说,它只允许其他类继承它,但不能实例化它。优点是它可以为所有子类强制执行某些层次结构。简单来说,它是一种强制所有子类遵循相同层次结构或标准的契约。

我也知道接口不是类。它是一个由“接口”一词定义的实体。接口没有实现;它只有签名,或者换句话说,只有方法的定义,没有主体。作为与抽象类的相似之处之一,它是一个契约,用于定义所有子类的层次结构,或者定义特定的方法集及其参数。它们之间的主要区别在于,一个类可以实现多个接口,但只能继承一个抽象类。由于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(使用前将#替换为@)

默认接口方法。抽象类和接口之间现在有什么深刻的、有意义的区别? 的相关文章

  • 如何在 C++ 中的文件末尾添加数据?

    我已按照网上的说明进行操作 此代码应该将输入添加到文件 数据库 的末尾 但当我检查时 数据会覆盖现有数据 请帮忙 这是我的代码 int main string name string address string handphone cou
  • 用 C++ 进行服装建模 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在编写一些软件 最终会绘制一个人体框架 可以配置各种参数 并且计划是在假人身上放置某种衣服 我研究
  • 在 C# 中创建具有单独列的分隔文本

    我一直在尝试在 C 中创建一个制表符限制的文本文件 以便数据正确显示在单独的列中 Firstname Lastname Age John Smith 17 James Sawyer 31 我尝试过 t 字符 但我得到的只是 Firstnam
  • VB.NET 相当于 C# 属性简写吗?

    是否有与 C 等效的 VB NET public string FirstName get set 我知道你能做到 Public Property name As String Get Return name ToString End Ge
  • std::cout 和 std::wcout 有什么区别?

    在c 中 有什么区别std cout and std wcout 它们都控制流缓冲区的输出或将内容打印到控制台 或者它们只是相似吗 它们作用于不同的字符类型 std cout uses char作为字符类型 std wcout uses w
  • 如何在 C# 中从 UNIX 纪元时间转换并考虑夏令时?

    我有一个从 unix 纪元时间转换为 NET DateTime 值的函数 public static DateTime FromUnixEpochTime double unixTime DateTime d new DateTime 19
  • 在 Unity 进程和另一个 C# 进程之间进行本地 IPC 的最快方法 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我希望每秒大约 30 次从 C 应用程序向我的 Unity 应用程序传送大量数据 由于 Unity 不支持映射内存和管道 我考虑了 t
  • XamlReader.Load 在后台线程中。是否可以?

    WPF 应用程序具有从单独的文件加载用户控件的操作 使用XamlReader Load method StreamReader mysr new StreamReader pathToFile DependencyObject rootOb
  • 单元测试一起运行时失败,单独运行时通过

    所以我的单元测试遇到了一些问题 我不能只是将它们复制并粘贴到这里 但我会尽力而为 问题似乎是 如果我一项一项地运行测试 一切都会按预期进行 但如果我告诉它一起运行测试 则 1 5 将通过 TestMethod public void Obj
  • 生成(非常)大的非重复整数序列而不进行预洗牌

    背景 我编写了一个简单的媒体客户端 服务器 我想生成一个不明显的时间值 随从客户端到服务器的每个命令一起发送 时间戳中将包含相当多的数据 纳秒分辨率 即使它不是真正准确 因为现代操作系统中计时器采样的限制 等 我想做的 在 Linux 上
  • 使用 C 语言使用 strftime() 获取缩写时区

    我看过this https stackoverflow com questions 34408909 how to get abbreviated timezone and this https stackoverflow com ques
  • 获取 WPF 控件的所有附加事件处理程序

    我正在开发一个应用程序 在其中动态分配按钮的事件 现在的问题是 我希望获取按钮单击事件的所有事件 因为我希望删除以前的处理程序 我尝试将事件处理程序设置为 null 如下所示 Button Click null 但是我收到了一个无法分配 n
  • 如何将自定义 JSON 文件添加到 IConfiguration 中?

    我正在使用 asp net Autofac 我正在尝试加载自定义 JSON 配置文件 并基于该文件创建 实例化 IConfiguration 实例 或者至少将我的文件包含到默认情况下构建的 IConfiguration asp net 中
  • 将 log4net 与 Autofac 结合使用

    我正在尝试将 log4net 与 Autofac 一起使用 我粘贴了这段代码http autofac readthedocs org en latest examples log4net html http autofac readthed
  • 如何编写一个同时需要请求和响应Dtos的ServiceStack插件

    我需要提供本地化数据服务 所有本地化的响应 Dto 都共享相同的属性 IE 我定义了一个接口 ILocalizedDto 来标记那些 Dto 在请求端 有一个ILocalizedRequest对于需要本地化的请求 Using IPlugin
  • 私有模板函数

    我有一堂课 C h class C private template
  • 有人可以提供一个使用 Amazon Web Services 的 itemsearch 的 C# 示例吗

    我正在尝试使用 Amazon Web Services 查询艺术家和标题信息并接收回专辑封面 使用 C 我找不到任何与此接近的示例 所有在线示例都已过时 并且不适用于 AWS 的较新版本 有一个开源项目CodePlex http www c
  • C++ 密码屏蔽

    我正在编写一个代码来接收密码输入 下面是我的代码 程序运行良好 但问题是除了数字和字母字符之外的其他键也被读取 例如删除 插入等 我知道如何避免它吗 特q string pw char c while c 13 Loop until Ent
  • Server.MapPath - 给定的物理路径,预期的虚拟路径

    我正在使用这行代码 var files Directory GetFiles Server MapPath E ftproot sales 在文件夹中查找文件 但是我收到错误消息说 给定物理路径但虚拟路径 预期的 我对在 C 中使用 Sys
  • 如何使用 Word Automation 获取页面范围

    如何使用办公自动化找到 Microsoft Word 中第 n 页的范围 似乎没有 getPageRange n 函数 并且不清楚它们是如何划分的 这就是您从 VBA 执行此操作的方法 转换为 Matlab COM 调用应该相当简单 Pub

随机推荐

  • cakePHP 文件下载未找到或不可读

    我现在已经挣扎了一个小时试图解决这个问题 我用它来下载文件app uploads 目录 它说目录未找到或不可读 但我检查了它 它也存在使用的文件 file File filename 我想知道我在这里缺少什么 file this gt Fi
  • 在executeBatch()之后使用CallableStatement检索ResultSet

    我需要多次调用存储过程并使用executeBatch 为了这 每次调用都应返回包含结果的表 但我无法访问此结果 接下来的代码工作正常 callableStatement setString 1 foo callableStatement s
  • 重新设计后如何拒绝来自 iTunes Connect 的二进制文件 (12/09/2014)?

    我需要拒绝我的二进制文件 以便重新上传 这一直是 iTunes connect 上的一个隐藏选项 现在重新设计了 我到处找都找不到 根据苹果自己的文档 从审核中删除您的版本 打开应用程序的 应用程序详细信息 页面 如中所述打开应用程序的 应
  • 如果安装了3.5,还需要.net Framework 2.0吗?

    我想知道如果安装了 net Framework 3 5 运行 net 2 0应用程序是否仍然需要 net Framework 2 0 谢谢 Net 3 5 实际上是 Net 2 0 加上一些额外功能 除非 Net 2 0 也存在 否则无法安
  • re.findall 表现得很奇怪

    源字符串是 Python 3 4 3 s r abc123d hello 3 1415926 this is my book 这是我的模式 pattern r 0 9 0 9 0 9 然而 re search可以给我正确的结果 m re s
  • 如何防止用户在 Ionic/Cordova 中截屏?

    是否可以阻止用户在使用 Ionic Cordova 开发的 Android 应用程序中截取屏幕截图 如果可以的话 怎样做 我在 Ionic 论坛上提问 但没有得到答案 是的 您可以使用插件来做到这一点 使用这里的一个 http blog d
  • 是否有使用 @Version 的可配置替代方案?

    我正在放置一个带注释的字段 Version在我所有的 JPA 域类中 但这似乎只是额外的样板 有没有办法通过配置来解决这个问题 TIA Ole 据 JPA 规范告诉我们 您无法更改 Version通过 配置 进行注释 你要么使用 Versi
  • 异步回发后如何保持整个页面滚动位置

    我正在使用 asp net 4 0 iis 7 5 microsoft Visual Studio 2010 我想要的是当异步回发发生时 更新面板 保持整个页面 浏览器 滚动位置 不是 div 或面板 我怎样才能做到这一点 实际上我有一个函
  • 动态添加到 TableLayoutPanel 的行显示在不同的行位置

    我正在尝试通过单击按钮将 TextBox 动态添加到 TableLayoutPanel 中 通过单击鼠标选择行 选择行后 单击按钮将在所选行号上插入文本框 Problem是正确之后显示在不同选定的行上使用 TextBox 3 或 4 次 进
  • 如何更改 ScrollBar 的宽度?

    我想更改 TFrame 的 ScrollingBar 宽度 我知道我可以通过以下方式更改系统中的所有 ScrollingBar SystemParametersInfo SPI SETNONCLIENTMETRICS 但是我该如何为特定的
  • Haskell 列表错误的部分和

    我需要在 Haskell 中编写一个函数 对列表的元素求和 直到某些特定元素存储在另一个列表中 例如partial add 1 2 3 4 5 6 2 5 0应该返回 3 12 6 我已经达到了这样的程度 partial add count
  • 删除数组中连续出现的重复项

    有什么方法可以从下面的数组中删除连续的重复项 同时只保留第一个重复项 该数组如下所示 a array 1 gt go 2 gt stop 3 gt stop 4 gt stop 5 gt stop 6 gt go 7 gt go 8 gt
  • 如何在 Mac OS cocoa 中获取已安装 USB 设备的设备 ID、供应商 ID 和产品 ID

    我正在尝试编写一个 Cocoa 程序来检测连接到 Mac OS 的 iPod 我正在监听 NSWorkspaceDidMountNotification 和 NSWorkspaceDidUnmountNotification 以获取 USB
  • JObject.Parse 与 JsonConvert.DeserializeObject

    JsonConvert DeserializeObject 和 JObject Parse 有什么区别 据我所知 两者都采用字符串并且都在 Json NET 库中 什么样的情况会让一种情况比另一种更方便 或者主要只是偏好 作为参考 下面是我
  • Azure API 管理:带有后端 API 的 Oauth2

    我有一个后端 API 想要使用 Azure API 管理进行代理 该后端 API 要求我提供 Bearer Oauth2 令牌 我想使用 Azure APIM 为我处理 Oauth2 流 并且我想公开一个非常简单的 API 供客户端应用程序
  • 如何在我的多面标签之一中包含希腊符号?

    我正在尝试使用 ggplot2 v 2 2 2 1 创建一个绘图facet wrap 并且我只需要在一个方面标签中包含一个希腊符号 共五个 我尝试使用 Stack Overflow 上发布的代码 R 分面网格中分面标签的 R 希腊字母和普通
  • OCaml 会将多参数函数转换为柯里化函数还是反之亦然?

    当我学习 OCaml 基础知识时 我被告知 OCaml 中的每个函数实际上都是一个只有一个参数的函数 多参数函数实际上是一个接受一个参数并返回一个函数 该函数接受下一个参数并返回 这是柯里化 我明白了 所以我的问题是 case 1 if I
  • OpenXmlPowerTools DocumentBuilder 在单独的页面上合并文档

    I am trying to merge 4 word documents and force content of each document starts at new page But instead of appending tex
  • 仅使用“小阴谋家”中的表格来展平列表

    我正在通过 The LIttle Scherer 来学习Scheme 作为一个老C程序员 作为练习 我尝试编写一个过程来使用以下方法来展平列表only 小阴谋家 中的表格 IE define lambda cond car cdr and
  • 默认接口方法。抽象类和接口之间现在有什么深刻的、有意义的区别?

    我知道抽象类是一种特殊的类 不能被实例化 抽象类只能被子类化 继承 换句话说 它只允许其他类继承它 但不能实例化它 优点是它可以为所有子类强制执行某些层次结构 简单来说 它是一种强制所有子类遵循相同层次结构或标准的契约 我也知道接口不是类