Questions tagged «inheritance»

继承是一种重用现有对象的代码或从现有对象建立子类型的方法,或两者​​都取决于编程语言的支持。

14
“偏爱组成而不是继承”的概念从何而来?
在过去的几个月中,“偏爱继承而不是继承”的口号似乎无处不在,并成为编程社区中的某种模因。每次看到它,我都会有些迷惑。就像有人在说“青睐锤子”。以我的经验,组合和继承是具有不同用例的两个不同工具,并且将它们视为可互换,并且一个在本质上优于另一个是没有意义的。 另外,我从来没有看到过真正的解释,说明为什么继承不好而组成很好,这让我更加怀疑。是否应该只凭信心接受?Liskov替换和多态性具有众所周知的明显好处,而IMO构成了使用面向对象编程的全部要点,而且从来没有人解释为什么应该丢弃它们以利于组合。 有谁知道这个概念的来历,其背后的原理是什么?

9
讨厌多重继承吗?
我一直很喜欢在一种语言中支持多重继承的想法。尽管通常是故意放弃的,但所谓的“替换”是接口。接口根本不能涵盖所有相同的多重继承,并且这种限制有时可能会导致产生更多样板代码。 我听说过的唯一基本原因是基类的钻石问题。我就是不能接受。对我来说,它的表现非常糟糕,例如:“嗯,有可能将其弄糟,所以这自然不是一个好主意。” 但是,您可以用编程语言修改任何内容,我的意思是。我只是不能认真对待这一点,至少没有没有更彻底的解释。 仅知道这个问题就占了90%。此外,我想我几年前听说过涉及通用解决方案的问题,该解决方案涉及“信封”算法或类似的东西(有人敲响铃吗?)。 关于钻石问题,我能想到的唯一潜在的真正问题是,如果您正在尝试使用第三方库,并且看不到该库中两个看似无关的类具有共同的基类,那么除了例如,文档是一种简单的语言功能,可能要求您明确声明要创建菱形的意图,然后才能为您实际编译菱形。有了这样的功能,任何钻石的制造要么是故意的,鲁ck的,要么是因为人们没有意识到这一陷阱。 所有人都这么说... 大多数人是否有真正的理由讨厌多重继承,还是仅仅是一堆歇斯底里会造成弊大于利?有没有我在这里看不到的东西?谢谢。 例 汽车扩展了WheeledVehicle,KIASpectra扩展了汽车和电子产品,KIASpectra包含无线电。为什么KIASpectra不包含电子产品? 因为它是电子的。继承vs.组合应该始终是is-a关系vs.has-a关系。 因为它是电子的。上下都有电线,电路板,开关等。 因为它是电子的。如果冬天电池没电了,您的麻烦就好像所有车轮突然丢失一样。 为什么不使用接口?以#3为例。我不想一遍又一遍地写这个,而且我真的不想创建一些奇怪的代理帮助器类来做到这一点: private void runOrDont() { if (this.battery) { if (this.battery.working && this.switchedOn) { this.run(); return; } } this.dontRun(); } (我们不会考虑该实现的好坏。)您可以想象如何可能有一些与电子相关的功能与WheeledVehicle中的任何内容都不相关,反之亦然。 我不确定是否要解决该示例,因为那里有解释的空间。您还可以考虑从平面扩展Vehicle和FlyingObject,以及从Bird扩展Animal和FlyingObject,或者从更纯粹的示例方面进行思考。

5
为什么我应该更喜欢合成而不是继承?
我总是读到,与继承相比,组合是首选。一对不同类型的博客文章,例如,提倡使用超过组成继承,但我看不出多态性是如何实现的。 但是我有一种感觉,当人们说喜欢组合时,他们的意思是更喜欢组合和接口实现的组合。您将如何在没有继承的情况下实现多态? 这是我使用继承的具体示例。如何将其更改为使用合成,我将获得什么? Class Shape { string name; public: void getName(); virtual void draw()=0; } Class Circle: public Shape { void draw(/*draw circle*/); }

12
如果我们重写SetWidth和SetHeight方法,为什么Square从Rectangle继承会出现问题?
如果Square是Rectangle的一种类型,那么为什么Square无法从Rectangle继承?还是为什么设计不好? 我听说有人说: 如果您使Square从Rectangle派生,那么Square应该可以在您期望矩形的任何地方使用 这里有什么问题?为何Square可以在您期望矩形的任何地方使用?仅当我们创建Square对象,并且重写Square的SetWidth和SetHeight方法时,它才可用,为什么会有任何问题呢? 如果您在Rectangle基类上具有SetWidth和SetHeight方法,并且Rectangle引用指向一个Square,则SetWidth和SetHeight毫无意义,因为设置一个将更改另一个以匹配它。在这种情况下,Square无法通过带有矩形的Liskov替代测试,并且从Square继承Square的抽象是一个不好的选择。 有人可以解释以上论点吗?同样,如果我们在Square中重写SetWidth和SetHeight方法,它是否可以解决此问题? 我也听说过: 真正的问题是我们不是在建模矩形,而是在“舒适的矩​​形”上建模,即在创建后可以修改宽度或高度的矩形(并且我们仍然将其视为同一对象)。如果我们以这种方式看待矩形类,很明显,正方形不是“可接受的矩形”,因为正方形无法重塑,并且仍然是正方形(通常)。在数学上,我们看不到问题,因为在数学环境中可变性甚至都没有意义 在这里,我认为“可调整大小”是正确的术语。矩形是“可调整大小的”,正方形也是如此。我在上述论点中缺少什么吗?可以像调整任何矩形一样调整正方形的大小。

7
什么时候在C#中使用抽象类代替具有扩展方法的接口?
“抽象类”和“接口”是相似的概念,其中接口是两者中比较抽象的。一个区别因素是抽象类在需要时为派生类提供方法实现。但是,在C#中,最近引入的扩展方法已减小了这种差异因素,该扩展方法使得可以为接口方法提供实现。另一个区别因素是,一个类只能继承一个抽象类(即没有多重继承),但可以实现多个接口。这使接口的限制更少,更加灵活。因此,在C#中,什么时候应该使用抽象类而不是具有扩展方法的接口? 接口+扩展方法模型的一个著名示例是LINQ,其中为IEnumerable通过多种扩展方法实现的任何类型提供了查询功能。

11
将程序分成多个类为什么很好?[关闭]
我仍然是一名高中学生(正在读10年级),并且还没有在学校学习实际的计算机课程。到目前为止,我所做的一切都是通过书本。这些书教会了我诸如继承的概念,但是将程序分成多个类又有什么帮助呢?这些书从未告诉过我。 我问这个问题主要是因为最近有一个项目。这是一款街机视频游戏,就像有人所说的Flash游戏一样(尽管我不知道Flash游戏是什么)。事实是,这只是一堂课。仅使用一个类,它就可以很好地工作(但是偶尔会有一些滞后)。所以,我只是问如何将其拆分为多个类会有所帮助。 这个项目是用Java编写的,我是唯一从事该项目的人。

17
OO编程真的和招聘公司一样重要吗?[关闭]
我正在完成我的硕士学位(计算机)并申请工作。我注意到许多公司专门要求了解面向对象。流行的访谈问题涉及继承,多态性,访问器等。 OO真的那么重要吗?我什至接受了C语言编程工作的面试,面试的一半是面向对象的。 在现实世界中,开发实际应用程序时,几乎总是使用面向对象吗?诸如多态性之类的关键功能是否大量使用? 我认为我的问题来自我的弱点之一。尽管我了解OO,但是似乎无法将其大量集成到我的程序中。

1
mixin或特性比纯多重继承更好吗?
C ++具有简单的多重继承,许多语言设计都将其视为危险。但是某些语言(例如Ruby和PHP)使用奇怪的语法来完成相同的操作,并将其称为mixin或traits。我多次听说,mixin /特性比普通的多重继承更难滥用。 是什么使它们危险性降低了?是否有不能用mixins / traits来实现,但是可以用C ++风格的多重继承来实现?他们有可能遇到钻石问题吗? 似乎我们在使用多重继承,但只是借口说它们是混合/特性,因此我们可以使用它们。

3
什么是类型系统?
背景 我正在设计一种语言,作为辅助项目。我有一个工作正常的汇编器,静态分析器和虚拟机。由于我已经可以使用构建的基础结构来编译和运行非平凡的程序,因此我考虑在大学里做一个演讲。 在我的演讲中,我提到VM提供了一种类型系统,有人问“ 您的类型系统用于什么? ”。回答后,我被问这个问题的人嘲笑。 因此,即使我几乎肯定会因提出这个问题而声名狼藉,但我还是去找程序员。 我的理解 据我了解,类型系统用于提供有关程序中实体的附加信息层,以便运行时,编译器或任何其他机器知道如何处理其所操作的位字符串。它们还有助于维护合同-编译器(或代码分析器,运行时或任何其他程序)可以验证程序在任何给定的点上以程序员期望其操作的值运行。 类型也可以用于向那些人类程序员提供信息。例如,我找到以下声明: function sqrt(double n) -> double; 比这更有用 sqrt(n) 前者提供了大量信息:sqrt标识符是一个函数,以一个double作为输入,并产生另一个double作为输出。后者告诉您它可能是一个带有单个参数的函数。 我的答案 因此,在被问到“您的类型系统是干什么的?”之后 我回答如下: 类型系统是动态的(类型被分配给值,而不是分配给包含它们的变量),但是强大,没有令人惊讶的强制规则(您不能将字符串添加到整数,因为它们表示不兼容的类型,但是您可以将整数添加到浮点数) 。 VM使用类型系统来确保指令的操作数有效。可供程序员使用,以确保传递给其函数的参数有效(即类型正确)。 类型系统支持子类型化和多重继承(这两种功能均可供程序员使用),并且在对对象使用动态方法分配时会考虑类型-VM使用类型来检查针对给定类型实现的给定消息的功能是什么。 后续问题是“如何将类型分配给值?”。因此,我解释了所有值都装在框内,并有一个指向类型定义结构的指针,该结构提供有关类型名称,其响应的消息以及其继承的类型的信息。 在那之后,我被嘲笑了,我的回答被“那不是一个真正的类型系统”打断了。 所以-如果我所描述的不符合“真实类型系统”的条件,那会是什么?那个人对我提供的内容不能视为类型系统是正确的吗?

8
LSP vs OCP / Liskov换人VS开盘关闭
我试图理解OOP的SOLID原则,并且得出的结论是LSP和OCP有一些相似之处(如果不多说的话)。 开放/封闭原则指出“软件实体(类,模块,功能等)应为扩展而开放,但为修改而封闭”。 LSP在简单的话指出,任何情况下Foo可以用的任何实例来代替Bar它源自Foo并计划将工作同样非常的方式。 我不是专业的OOP程序员,但在我看来,只有在Bar派生自LSP Foo不会更改其中任何内容而只能扩展它的情况下,LSP才是可能的。这意味着特别是程序LSP仅在OCP为true时才为true,而OCP仅在LSP为true时才为true。那意味着他们是平等的。 如果我错了纠正我。我真的很想了解这些想法。非常感谢您的回答。

5
为什么继承一个类而不添加属性?
我在我们的(相当大的)代码库中发现了一个继承树,如下所示: public class NamedEntity { public int Id { get; set; } public string Name { get; set; } } public class OrderDateInfo : NamedEntity { } 据我所知,它主要用于绑定前端的东西。 对我来说,这很有意义,因为它为类提供了具体的名称,而不是依赖于generic NamedEntity。另一方面,有许多这样的类根本没有其他属性。 这种方法有什么缺点吗?

11
仅限构造方法的子类:这是反模式吗?
我当时正在与一位同事进行讨论,但最终我们对继承的目的产生了矛盾的直觉。我的直觉是,如果子类的主要功能是表达其父级的可能值的有限范围,则它可能不应该是子类。他主张相反的直觉:子类化表示对象的“特定性”更高,因此子类关系更合适。 更具体地讲,我认为如果我有一个扩展父类的子类,但是该子类覆盖的唯一代码是构造函数(是的,我知道构造函数通常不会“重写”,请耐心等待),然后真正需要的是一种辅助方法。 例如,考虑一下这个现实生活的类: public class DataHelperBuilder { public string DatabaseEngine { get; set; } public string ConnectionString { get; set; } public DataHelperBuilder(string databaseEngine, string connectionString) { DatabaseEngine = databaseEngine; ConnectionString = connectionString; } // Other optional "DataHelper" configuration settings omitted public DataHelper CreateDataHelper() { Type dataHelperType = DatabaseEngineTypeHelper.GetType(DatabaseEngine); DataHelper …


11
抽象类/方法过时了吗?
我曾经创建许多抽象类/方法。然后我开始使用接口。 现在,我不确定接口是否不会使抽象类过时。 您需要一个完全抽象的类吗?创建一个接口。您需要一个带有一些实现的抽象类吗?创建一个接口,创建一个类。继承该类,实现接口。另一个好处是某些类可能不需要父类,而只实现接口。 那么,抽象类/方法是否过时了?

3
“构成超越继承”是否违反了“枯燥原则”?
例如,考虑我有一个可供其他类扩展的类: public class LoginPage { public String userId; public String session; public boolean checkSessionValid() { } } 和一些子类: public class HomePage extends LoginPage { } public class EditInfoPage extends LoginPage { } 实际上,子类没有任何方法可以覆盖,也不会以通用方式访问HomePage,即:我不会做类似的事情: for (int i = 0; i < loginPages.length; i++) { loginPages[i].doSomething(); } 我只想重用登录页面。但是根据https://stackoverflow.com/a/53354,我在这里更喜欢合成,因为我不需要LoginLog接口,所以在这里我不使用继承: public class HomePage { …

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.