为什么要使用继承? [关闭]

2024-04-27

我知道问题是之前讨论过 https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance,但似乎总是假设继承至少有时比组合更可取。我想挑战这个假设,希望获得一些理解。

我的问题是这样的:Since你可以通过对象组合完成任何你可以通过经典继承完成的事情自从经典继承经常被滥用[1]自从对象组合使您可以灵活地更改委托对象运行时,为什么你会ever使用经典继承?

我可以理解为什么您会建议使用某些语言(例如 Java 和 C++)进行继承,因为这些语言不提供方便的委托语法。在这些语言中,只要没有明显错误,就可以通过使用继承来节省大量输入。但其他语言(例如 Objective C 和 Ruby)都提供经典继承and非常方便的委托语法。据我所知,Go 编程语言是唯一一种认为经典继承麻烦大于其价值并且仅支持代码重用委托的语言。

陈述我的问题的另一种方式是这样的:即使您知道经典继承对于实现某个模型来说并不是不正确,但是这个理由是否足以使用它而不是组合?

[1] 许多人使用经典继承来实现多态性,而不是让他们的类实现接口。继承的目的是代码重用,而不是多态。此外,有些人使用继承来模拟他们对“is-a”关系的直观理解这通常会出现问题 http://en.wikipedia.org/wiki/Circle-ellipse_problem.

Update

我只是想澄清一下当我谈论继承时我的确切含义:

我正在谈论类从部分或完全实现的基类继承的继承类型 http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming). I am not谈论从纯粹的抽象基类继承,这与实现接口是一样的,我郑重声明,我并不反对这一点。

Update 2

我知道继承是C++实现多态性的唯一方法。在这种情况下,很明显为什么你必须使用它。所以我的问题仅限于 Java 或 Ruby 等语言,它们提供了实现多态性的不同方法(分别是接口和鸭子类型)。


[注意:这个问题最初被标记为与语言无关。基于此,这个答案的编写与语言无关,因此它讨论了在多种语言(例如 Smalltalk、C++ 和 Object Pascal)中使用的继承。此后它被重新标记为专门针对 Java。 Java 的不同之处在于定义class and an interface作为两个完全独立的事物。继承的目的是代码重用而不是多态性的想法从特定于 Java 的角度来看是合理的,但从与语言无关的角度来看显然是错误的。如果您只关心 Java,这可能不是最好的答案。]

继承的目的是代码重用,而不是多态。

这是你的根本错误。事实几乎恰恰相反。这primary(公共)继承的目的是对相关类之间的关系进行建模。多态性是其中很大一部分。

如果使用正确,继承并不是重用现有代码。相反,它是关于被使用by现有代码。也就是说,如果您有可以与现有基类一起使用的现有代码,那么当您从现有基类派生一个新类时,其他代码现在也可以自动与您的新派生类一起使用。

可以使用继承来重用代码,但是当/如果您这样做时,通常应该是private继承不是公共继承。如果您使用的语言很好地支持委派,那么您很可能没有太多理由使用私有继承。 OTOH,私有继承确实支持委托(通常)不支持的一些功能。特别是,尽管多态性在这种情况下绝对是次要问题,但它can仍然是一个问题——即,通过私有继承,您可以从基类开始almost你想要什么,并且(假设它允许)覆盖不太正确的部分。

对于委派,您唯一真正的选择是完全按原样使用现有类。如果它没有达到您想要的效果,您唯一真正的选择就是完全忽略该功能,并从头开始重新实现它。在某些情况下,这并不算什么损失,但在其他情况下,损失却相当可观。如果基类的其他部分使用多态函数,则私有继承允许您重写only多态函数,其他部分将使用您重写的函数。通过委派,您无法轻松插入新功能,因此现有基类的其他部分将使用您已覆盖的功能。

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

为什么要使用继承? [关闭] 的相关文章

  • Maven 管理的 Java EE 应用程序中 JBoss 提供的库

    这对我来说实际上不太可能 但网上似乎没有关于将 JBoss 提供的依赖项导入 Maven 管理的 Java EE 应用程序以在其中部署的直接答案 据我所知 有两件事与这个问题有关 那就是jboss as client外部 就 JVM 而言
  • 构建 jar 后无法运行 exe

    我制作了一个简单的实用应用程序 其中我有一个要运行的exe文件 我通过使用它来运行 Runtime getRuntime exec this getClass getResource filename exe getPath 当我从 ide
  • 访问 java jigsaw 模块中的资源文件[重复]

    这个问题在这里已经有答案了 我正在尝试从项目中的类访问 Eclipse 项目中的文件 我需要将该项目声明为 jigsaw 模块才能从其他项目访问它 但是通过这样做 我无法再访问项目中的 example png 等文件 这是我的项目结构 pr
  • Java RMI 通过互联网

    我正在用 Java 开发一个游戏 使用 RMI 进行所有网络通信 RMI 允许我调用服务器上的方法 但这对我来说还不够 我还希望服务器能够在连接的客户端之间传播消息 我的客户端查找服务器 它的接口扩展了远程 并在其上注册 它允许服务器知道谁
  • java IO将一个文件复制到另一个文件

    我有两个 Java io File 对象 file1 和 file2 我想将 file1 的内容复制到 file2 有没有一种标准方法可以做到这一点 而无需我创建一个读取 file1 并写入 file2 的方法 不 没有内置方法可以做到这一
  • Java中的String为什么是不可变的对象,但我在创建一个对象后仍然可以更改它的值? [复制]

    这个问题在这里已经有答案了 如果我可以创建一个字符串并给它一个值 这怎么可能呢 然后 我可以像这样简单地覆盖它的值 String a abc a def 我怎么可能改变的值a 我一定在这里遗漏了一些东西 我知道每当创建 String 对象时
  • 无法在 Spring boot 中使用 findOne() 方法

    我的项目是关于用户管理器网络的 我是 Spring 和 Java 的新手 这是我的代码 在 UserController 中 RequestMapping value users name method RequestMethod GET
  • spring启动时如何加载@Cache?

    我正在使用 spring cache 来改进数据库查询 其工作原理如下 Bean public CacheManager cacheManager return new ConcurrentMapCacheManager books Cac
  • 适当支持不区分大小写的映射

    我想实现一个不区分大小写的哈希映射 这个问题本身并不新鲜 但我想添加额外的功能 但不知道要采取什么总体方向 我希望客户能够做这样的事情 boolean preserve case true Map
  • C++:重写由另一个方法调用的受保护方法

    我有一个关于 C 继承的非常基本的问题 class A public void foo print protected void print class B public A protected void print std cout lt
  • Postgres UUID 和休眠

    我有一个具有 UUID 列的实体 它不是主键 我正在使用 Postgres 和 hibernate 我对此专栏的类型是https www postgresql org docs 9 1 static datatype uuid html h
  • 如何为我的数独游戏制作 GUI? (摇摆)

    到目前为止 我已经编写了生成随机 9x9 数独网格的代码 我是Java的初学者 所以我有一些关于如何做UI的问题 显示数字的最佳方式是什么 我尝试创建 81 个 JTextFields 这非常乏味 而且我确信有一种有效的方法可以做到这一点
  • Cordova Android 应用程序中的网页不可用

    编辑 我一直在解决这个问题并回顾我的所有步骤 我很乐意缩小这个问题的规模 并在令人困惑的情况下获得更多确切的细节 目前 我觉得 Keycloak 似乎只想将我重定向到 https 据我所知 这应该是 Wildfly 服务器配置问题 编辑 我
  • 如何将捕获的图像写入/粘贴到文档文件?

    我有一个场景 我需要捕获图像并将它们一个接一个地写入到一个word文件中 我已经编写了下面的代码 但似乎不起作用 请帮忙 Robot robot try robot new Robot BufferedImage screenShot ro
  • jstack 是否停止在较新的 JDK8 版本上工作?

    我惊讶地发现 不知何故 最近 jstack 停止了在较新的 JDK 8 上的工作 我不确定这发生在哪个版本 但我确实得到 36649 Unable to open socket file target process not respond
  • 更改 Logger 实例的全局设置

    我在用着java util logging Logger http download oracle com javase 1 4 2 docs api java util logging Logger html作为我的应用程序的日志引擎 每
  • Java中如何对整数除法进行四舍五入并得到int结果? [复制]

    这个问题在这里已经有答案了 我刚刚写了一个小方法来计算手机短信的页数 我没有选择使用Math ceil 老实说 它看起来很丑陋 这是我的代码 public class Main param args the command line arg
  • 使用 System.currentTimeMillis() 每秒运行一次代码

    我试图使用 System currentTimeMillis 每秒运行一行代码 代码 while true long var System currentTimeMillis 1000 double var2 var 2 if var2 1
  • 如何使用 itext 在 pdf 页脚上添加页码,它应该照顾其宽度?

    我的代码示例如下 Override public void onEndPage PdfWriter writer Document document addFooter writer private void addFooter PdfWr
  • 在 Eclipse Testrunner 中使用名称的 ParameterizedTest

    当您使用 Eclipse TestRunner 运行 JUnit 4 ParameterizedTest 时 图形表示相当愚蠢 对于每个测试 您都有一个名为 0 1 ETC 是否可以进行测试 0 1 等显式名称 实施一个toString测试

随机推荐

  • 如何向我的 Android 应用程序授予系统权限?

    我正在实现一个从设备上静默卸载应用程序的演示 在 adb shell 中 我可以使用 pm uninstall packagename 来执行任务 但是当我编写代码时 我收到了一些权限被拒绝的错误 我已经用谷歌搜索了一段时间 发现要获得 D
  • 在 JPanel 与 JComponent 中绘图

    我需要一些帮助来理解为什么 JComponent 与 JPanel 中的绘图工作方式不同 import java awt Color import java awt Graphics import java awt Graphics2D i
  • 跨平台移动应用程序开发框架如何工作?

    Rhodes Phonegap 和 Appcelerator 如何采用 Javascript 或 Ruby 并将它们编译成应用程序 SDK 的二进制文件 而这些应用程序 SDK 通常需要使用 Obj C Java 和其他语言编写应用程序 A
  • 实体框架,将视图映射到表

    我有一个基本视图 它返回与表相同的列 给出或获取 1 个字段 在我的 DAL 代码中 我返回 MyTableObject 的列表 但在某些情况下 我将调用视图返回相同的数据 但来自不同的源 List
  • Titanium 创建图像文件:file.write(blob) 未创建正确的文件

    我正在尝试使用 Titanium 1 8 1 读取 PNG 文件 这是我读取文件的代码 var f Ti Filesystem getFile Ti Filesystem resourcesDirectory KS nav views pn
  • Cython 中的抽象类(具有纯虚方法)

    快速版本 如何在 Cython 中声明抽象类 目标是只声明接口 以便其他类可以继承它 必须有没有实施这个班级的 接口 pxd cdef class IModel cdef void do smth self impl pyx from in
  • 使用 Sethi-Ullman 算法的表达式的代码生成器

    Give a AST tree http en wikipedia org wiki Abstract syntax tree 我想生成一种类似汇编的语言 我正在尝试使用塞西 乌尔曼 http en wikipedia org wiki S
  • 使用 NSPredicate 过滤 NSArray

    我想过滤一个数组User对象 User has fullname user id和一些更多的属性 根据firstName or lastName以一些字符串开头 我知道如何根据一种条件进行过滤 NSPredicate predicate N
  • 将jquery日期选择器集成到jsf中

    我正在关注这些例子here http jqueryui com demos datepicker icon trigger and here http jqueryui com demos datepicker icon trigger但我
  • 可以制作一个不调用Intent的Android通知吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何对表中的每一行运行特定的sql查询?

    所以我的数据库中有两个表 它们看起来都是这样的 通讯 拨打电话 Timestamp FromIDNumber ToIDNumber GeneralLocation 2012 03 02 09 02 30 878 674 Grasslands
  • 成员函数什么时候应该有 const 限定符,什么时候不应该有?

    大约六年前 一位名叫 Harri Porten 的软件工程师写道本文 http www froglogic com porten const html 提出这样的问题 成员函数什么时候应该有 const 限定符 什么时候不应该有 我发现这是
  • 查找最近的城市,例如 oodle.com

    因此 我正在尝试开发一个显示用户列表的应用程序 该网站应该检测用户位置 我为此使用 maxmind api 然后显示用户位置 用户指定半径内的城市的列表 我该怎么做呢 MaxMind API 让我可以通过 IP 地址检测用户的城市 但如何找
  • dprintf 与 break + 命令 + continue 之间有什么区别?

    例如 dprintf main hello n run 生成与以下内容相同的输出 break main commands silent printf hello n continue end run 使用是否有显着的优势dprintf ov
  • C# 中的嵌入字体

    我已经尝试了很多在 c 中的 wpf 应用程序中嵌入字体的方法 该字体的名称是 Roboto 文件名是机器人 ttf如果那有用的话 我已确保它已在程序集中编译 那么如何在a中应用字体TextBlock例如 您可以将字体应用到如下元素中
  • 在插入模式下移至行首

    我知道我可以使用 Home in insert mode Esc i to exit insert mode and enter it again effectively going to the beginning of line But
  • 如何使用 devise_invitable 发送自定义邀请

    我是 ruby 新手 使用 devise invitable gem 进行邀请 每条指令都正确发送 现在我想添加一个自定义主题 该主题将具有受邀者姓名和董事会名称以及与主题相同的自定义内容 我如何在以下操作方法中执行此操作而不使用额外的自定
  • git log --oneline --graph 输出的含义

    我正在学习相对提交引用并尝试理解以下内容git log oneline graph课程中提供的输出 在课程中它说给定的 HEAD 指向9ec05ca提交 HEAD 意思是曾祖父母提交 是0c5975a犯罪 但在我看来4c9749e如果每个
  • 如何将H2数据库文件存储到项目目录中

    当我使用H2数据库时 数据库文件存储在C Users MyName TestDataBase db目录 H2路径是jdbc h2 TestDataBase 这是默认的 H2 数据库路径 是否有可能像这样将 H2 数据库文件存储到我的项目目录
  • 为什么要使用继承? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi