界面与组合

2024-05-09

我想我理解接口和抽象之间的区别。抽象设置默认行为,在纯抽象的情况下,行为需要由派生类设置。接口是您所需要的,无需基类的开销。那么接口相对于组合的优势是什么?我能想到的唯一优点是在基类中使用受保护的字段。我缺少什么?


你的标题没有意义,你的解释有点模糊,所以让我们定义这些术语(并介绍关键的缺失术语)。

这里发生了两件不同的事情:

  • 抽象类与接口
  • 继承与组合

让我们从接口和抽象类开始。

  • An 抽象类(在 C++ 中)是一个无法实例化的类,因为它的至少一个方法是纯虚方法。
  • An 界面,在类似 Java 的语言中,是一组没有实现的方法,在 C++ 中它被模拟为抽象类仅使用纯虚方法。

因此,在 C++ 上下文中,两者之间没有太大区别。特别是因为这种区别从未考虑到自由函数。

例如,考虑以下“接口”:

class LessThanComparable {
public:
    virtual ~LessThanComparable() {}

    virtual bool less(LessThanComparable const& other) const = 0;
};

即使使用免费函数,您也可以轻松地增强它:

inline bool operator<(LessThanComparable const& left, LessThanComparable const& right) {
    return left.less(right);
}

inline bool operator>(LessThanComparable const& left, LessThanComparable const& right) {
    return right.less(left);
}

inline bool operator<=(LessThanComparable const& left, LessThanComparable const& right) {
    return not right.less(left);
}

inline bool operator>=(LessThanComparable const& left, LessThanComparable const& right) {
    return not left.less(right);
}

在这种情况下,我们提供行为......但类本身仍然是一个接口......哦,好吧。


因此,真正的争论在于遗产 and 作品.

继承经常被滥用来继承行为。这不好。应该使用继承来建模is-a关系。否则,您可能需要组合。

考虑简单的用例:

class DieselEngine { public: void start(); };

现在,我们如何构建一个Car有了这个 ?

如果你继承的话,它会起作用。然而,突然你得到这样的代码:

void start(DieselEngine& e) { e.start(); }

int main() {
    Car car;
    start(car);
}

现在,如果您决定更换DieselEngine with WaterEngine,以上功能不起作用。编译失败。并且拥有WaterEngine继承自DieselEngine当然感觉很ikky...

那解决办法是什么?作品.

class Car {
public:
    void start() { engine.start(); }

private:
    DieselEngine engine;
};

这样,没有人可以编写无意义的代码来假设汽车是发动机(哦!)。因此,更换发动机是easy绝对与没有客户影响.

这意味着您的实现与使用它的代码之间的一致性较差;或通常所说的:更少的耦合.


经验法则是,一般来说,从具有数据或实现行为的类继承应该是不受欢迎的。它可以是合法的,但通常有更好的方法。当然,就像所有的经验法则一样,我们对此持保留态度。小心过度设计。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

界面与组合 的相关文章

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

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

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在编写一些软件 最终会绘制一个人体框架 可以配置各种参数 并且计划是在假人身上放置某种衣服 我研究
  • std::cout 和 std::wcout 有什么区别?

    在c 中 有什么区别std cout and std wcout 它们都控制流缓冲区的输出或将内容打印到控制台 或者它们只是相似吗 它们作用于不同的字符类型 std cout uses char作为字符类型 std wcout uses w
  • 向 Nhibernate 发出 SQL 查询

    如何将此 SQL 查询发送给 Nhibernate SELECT Customer name FROM Company INNER JOIN Customer ON Company CompanyId Customer CompanyId
  • 如何在 C# 中从 UNIX 纪元时间转换并考虑夏令时?

    我有一个从 unix 纪元时间转换为 NET DateTime 值的函数 public static DateTime FromUnixEpochTime double unixTime DateTime d new DateTime 19
  • 在新的浏览器进程中打开 URL

    我需要在新的浏览器进程中打开 URL 当浏览器进程退出时我需要收到通知 我当前使用的代码如下 Process browser new Process browser EnableRaisingEvents true browser Star
  • XamlReader.Load 在后台线程中。是否可以?

    WPF 应用程序具有从单独的文件加载用户控件的操作 使用XamlReader Load method StreamReader mysr new StreamReader pathToFile DependencyObject rootOb
  • C# Dns.GetHostEntry 不返回连接到 WiFi 的移动设备的名称

    我有一个 C 中的 Windows 窗体应用程序 我试图获取列表中所有客户端的主机名 下面给出的是 ra00l 来自此链接的代码示例 GetHostEntry 非常慢 https stackoverflow com questions 99
  • 如何在 C# 中定义文本框数组?

    您好 当我在 Windows 申请表上创建文本框时 我无法将其命名为 box 0 box 1 等 我这样做的目的是因为我想循环使用它们 其实我发现TextBox array firstTextBox secondTextBox 也有效
  • 获取 WPF 控件的所有附加事件处理程序

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

    在 C 中使用线程时 我面临警告 警告 从不同大小的整数转换为指针 代码如下 include
  • C++:.bmp 到文件中的字节数组

    是的 我已经解决了与此相关的其他问题 但我发现它们没有太大帮助 他们提供了一些帮助 但我仍然有点困惑 所以这是我需要做的 我们有一个 132x65 的屏幕 我有一个 132x65 的 bmp 我想遍历 bmp 并将其分成小的 1x8 列以获
  • 如何使用 watin 中的 FileUploadDialogHandler 访问文件上传对话框

    我正在使用 IE8 和 watin 并尝试通过我的网页测试上传文件 我不能简单地使用 set 方法设置上传文件 例如 ie FileUpload Find ById someId Set C Desktop image jpg 因为上传文本
  • 批量更新 SQL Server C#

    我有一个 270k 行的数据库 带有主键mid和一个名为value 我有一个包含中值和值的文本文件 现在我想更新表格 以便将每个值分配给正确的中间值 我当前的方法是从 C 读取文本文件 并为我读取的每一行更新表中的一行 必须有更快的方法来做
  • 如何将自定义 JSON 文件添加到 IConfiguration 中?

    我正在使用 asp net Autofac 我正在尝试加载自定义 JSON 配置文件 并基于该文件创建 实例化 IConfiguration 实例 或者至少将我的文件包含到默认情况下构建的 IConfiguration asp net 中
  • 使用 Moq 使用内部构造函数模拟类型

    我正在尝试模拟 Microsoft Sync Framework 中的一个类 它只有一个内部构造函数 当我尝试以下操作时 var fullEnumerationContextMock new Mock
  • 有人可以提供一个使用 Amazon Web Services 的 itemsearch 的 C# 示例吗

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

    我需要一个循环链表 所以我想知道是否LinkedList是循环链表吗 每当您想要移动列表中的 下一个 块时 以循环方式使用它的快速解决方案 current current Next current List First 电流在哪里Linke
  • C++ 密码屏蔽

    我正在编写一个代码来接收密码输入 下面是我的代码 程序运行良好 但问题是除了数字和字母字符之外的其他键也被读取 例如删除 插入等 我知道如何避免它吗 特q string pw char c while c 13 Loop until Ent
  • 为什么在setsid()之前fork()

    Why fork before setsid 守护进程 基本上 如果我想将一个进程与其控制终端分离并使其成为进程组领导者 我使用setsid 之前没有分叉就这样做是行不通的 Why 首先 setsid 将使您的进程成为进程组的领导者 但它也

随机推荐

  • 如何授权 Swagger 使用 MS Graph API

    我们正在为 MS Graph API 构建 Web API 包装器 我想使用 Swagger 来测试我的 API 但我无法正确配置 我不断收到错误请求 但没有其他线索 我无法在这台公司笔记本电脑上安装 Fiddler 或其他工具来帮助我进行
  • 在 Python 3 中动态导入模块的问题

    我遇到的情况是 在我的 Python 3 项目中 在运行时必须包含某些模块 我在用着importlib import module为了这 第二次更新 我确实找到了一种方法来做一些接近我想要的事情 一些额外的代码可能会使我的一些链接稍微偏离一
  • 如何使用 java/vb 脚本调用自定义 ActiveX dll 中的方法

    我使用 VB6 创建了一个 ActiveX dll 并使用打包和部署向导将其打包 生成了一个 cab 文件和一个演示 HTML 页面 此 ActiveX dll 包含一个 simgle 方法 该方法返回字符串且不接受任何参数 我遇到的麻烦是
  • PAM 在 C 中验证用户

    好吧 所以我是一个非常糟糕的编码员 我想知道 如标题所示 如何使用 C 语言通过 PAM 验证 Linux 用户 我唯一真正理解的是包括pam appl h and pam misc h我需要放置的头文件pam start and pam
  • 如何使用 Spring Security 跨多个基于 JVM 的应用程序实现单点登录

    我目前正在尝试跨多个基于 JVM Grails Servlet 的 Web 应用程序实现单点登录解决方案 这些应用程序目前都部署在同一个 servlet 容器 当前是 Tomcat 但不想将我的解决方案仅限于 Tomcat 中 所有 Web
  • 使用 Jest 和 Testbed 测试 Angular 9 服务

    在我的 Angular 9 项目中我添加了jest并删除Jasmine and Karma 我正在测试一项名为CorrectionService依赖于一个名为的服务RemoteService 我想监视RemoteService查看是否调用了
  • C# 中将一个字符串拆分为另一个字符串

    我一直在使用Split 分割字符串的方法 但这似乎仅在您按字符分割字符串时才有效 有没有办法分割一个string 另一个字符串是按参数分割的 我尝试将拆分器转换为字符数组 但没有成功 换句话说 我想分割string THExxQUICKxx
  • 如何使用 facebook API 在 javascript 中获取好友列表

    我不熟悉使用 Facebook Javascript SDK 我的故事是当我访问网站时它会在网页上显示我所有的朋友 照片和姓名 我注册了 Facebook API 和 App ID 我把网站网址设置为http 本地主机 81 http lo
  • 有条件填写 pandas 数据框

    我有一个数据框df列中包含浮点值A 我想添加另一列B这样 B 0 A 0 for i gt 0 B i if np isnan A i then A i else Step3 B i if abs B i 1 A i B i 1 lt 0
  • 将 PHP 变量保存到文本文件

    我想知道如何将 PHP 变量保存到 txt 文件 然后 再次检索它们 Example 有一个输入框 提交后写的东西 输入框将被保存到文本文件中 稍后需要结果 作为变量带回 假设变量是 text I 需要将其保存到文本文件并能够将其检索回来
  • 如何使用 Google Apps 脚本编辑现有的 Google 表单项(问题)

    我有一个谷歌脚本来构建谷歌表单 该脚本使用包含问题和相应选项的电子表格填写表单 表格中显示的问题需要定期更新 我希望通过更改电子表格中的问题来更新表单中的问题 如下所示 I use onOpen 对于脚本 以便每次访问表单时 脚本都会重建最
  • 获取单词中重复次数最多的字母的数量

    我正在尝试计算单词中重复次数最多的字母的数量 function GreatestCount str var count for var i 0 i
  • 如何在 Java 中安装附加包?

    我对 Java 很陌生 我想使用名为的包中的一些功能daj 教程代码有以下几行 import daj import java util import java lang Math import Msg 但第一行和第四行会产生红色下划线 导致
  • 生成 CloudFront 签名 URL 时性能缓慢

    我正在按照此示例使用 PHP 在 CloudFront 上创建签名 URLhttp docs aws amazon com AmazonCloudFront latest DeveloperGuide CreateURL PHP html
  • 等待 JavaScript 中 Json 调用完成

    我正在使用下面的json调用在我的 javascript 方法中 function go123 var cityName var temp getJSON https abc in api city callback args functi
  • 如何检索 jquery $.ajax 对象的responseJSON属性[重复]

    这个问题在这里已经有答案了 我有这个 JavaScript ajax ajax type GET url DBConnect php data dataType json success function data error functi
  • 从 JavaScript 中 Firebase 数据库的查询结果中获取特定子项的值

    我在 Firebase 上有这个示例数据库 样本数据库 我有一个index html 其中有这两个输入文本 div class login form h2 Login Form h2 div
  • 对过期会话进行休息调用:HTTP 401 响应导致浏览器显示登录窗口

    我编写了一个 HTML 5 应用程序 它使用 AngularJS 并与在 Tomcat 上运行的 Java REST 后端进行交互 我使用 Spring Security 来处理登录和安全性 当用户进入网站时 他将被转发到登录页面 该页面创
  • 从 Cox PH 模型预测概率

    我正在尝试使用 cox 模型来预测时间 称为停止 3 后失败的概率 bladder1 lt bladder bladder enum lt 5 coxmodel coxph Surv stop event rx size number cl
  • 界面与组合

    我想我理解接口和抽象之间的区别 抽象设置默认行为 在纯抽象的情况下 行为需要由派生类设置 接口是您所需要的 无需基类的开销 那么接口相对于组合的优势是什么 我能想到的唯一优点是在基类中使用受保护的字段 我缺少什么 你的标题没有意义 你的解释