Oop 何时使用继承?

Oop 何时使用继承?,oop,inheritance,Oop,Inheritance,我和我的朋友进行了一场小辩论。 我必须实现一个“browser process watcher”类,该类在被监视的浏览器(比如Internet explorer)运行时调用事件 我们创建了一个“流程观察者”类,现在开始讨论: 他说构造函数应该只接受字符串(比如“iexplore.exe”),我说我们应该继承“Process watcher”来创建一个“browser watcher”,它接受当前使用的浏览器枚举,构造函数将其“转换”为“iexplore”。 他说我们应该使用一个util函数来充当

我和我的朋友进行了一场小辩论。 我必须实现一个“browser process watcher”类,该类在被监视的浏览器(比如Internet explorer)运行时调用事件

我们创建了一个“流程观察者”类,现在开始讨论:

他说构造函数应该只接受字符串(比如“iexplore.exe”),我说我们应该继承“Process watcher”来创建一个“browser watcher”,它接受当前使用的浏览器枚举,构造函数将其“转换”为“iexplore”。 他说我们应该使用一个util函数来充当翻译器


我知道这两种方法都是有效的和好的,但我想知道每种方法的优点和缺点是什么,在我们的情况下什么是合适的。

取决于你有什么用例或你遵循什么上帝


我没有说“继承是邪恶的”,但通常我遵循“偏爱组合而非继承”的原则,以避免过多的类层次结构。

在其他条件相同的情况下,我更喜欢更简单的解决方案(一个以字符串作为构造函数参数的单一具体类),而不是更复杂的解决方案(使用基类和子类)


当您想要改变行为时,继承是合适的:如果浏览器观察者将做普通进程观察者不做的事情。但是,如果您只想更改数据的值,那么只需更改数据。

继承只能用于实现“isa”关系

正如您可以说“浏览器观察者”是“流程观察者”的一个特定实例,那么继承适用于此体系结构

因此,对我来说,作为“流程观察者”的浏览器观察者实现构造的一部分,拥有您正在观看的内容的身份无疑是一条必由之路

编辑:更具体地说,当您想要专门化行为时,继承是为您准备的。例如,大多数动物都会发出声音,但如果你希望在一个名为“动物”的课程中提供要发出的声音,你必须等待专业化

所以我们有马类为它的声音提供“嘶鸣”,狗类为它的声音提供“吠叫”,等等

干杯


Rob

如果ProcessWatcher除了作为BrowserWatcher的父级之外没有其他用途,那么就不应该创建它。如果正在实现的其他观察者具有可放置在ProcessWatcher中的共享功能,那么您应该这样做(两者都是“isa”关系,因此满足Rob的标准)


其实就这么简单。认为有一天你会有其他的观察者,这不是支持创建一个单独的类的论点。这是一种心理上的抽搐,你应该尽快放弃。

最近,我一直在采取“现在保持简单,如果需要扩展,以后重构”的方法

你现在所做的似乎很简单。你只有一个案子要处理。所以我想说现在采取更简单的方法。最后,如果你永远不需要做另一种观察者,那么你将避免额外的复杂性。然而,如果需要的话,编写代码的方式将使以后重构更容易

将来,如果您发现您需要另一种类型的观察者,那么花点精力将其重构为继承(或组合,或任何您想要遵循的其他模式)。如果您的初始代码正确完成,重构应该相当容易,因此您不会真正增加太多额外的工作


我发现这种方法对我来说相当有效。在我真的不需要继承的情况下,代码保持简单。但是当我真的需要它的时候,我可以添加它而没有任何实际问题。

我同意,在大多数情况下,简单而不是复杂是一个好策略,只要你的简单不是太短视(参考Herms,编写代码的方式可以让你以后很容易地重新考虑)

然而,我也知道,要把那个鼓励进行更彻底设计的bug堵在耳朵里是多么困难。如果您仍然希望支持继承,而不必考虑“基类”和“子类”,那么您可以简单地定义一个由ProcessWatcher实现的接口(例如IPProcessWatcher)。当您使用ProcessWatcher对象时,请根据接口引用它,这样,如果您以后决定创建BrowserWatcher(或任何其他类型的ProcessWatcher),只要它实现IPProcessWatcher接口,就可以不强制它从ProcessWatcher下降

警告:小心操作。想要为每一个对象定义一个接口是很有诱惑力的,让我们面对现实吧,这太荒谬了。=)

最终,您需要找到一些您都熟悉的东西,因为您都必须维护这段代码,我认为这可能是一个很好的折衷方案,而不是简单的“继承或不继承”


祝你好运

用一句非常简单的话可以说:

当您需要使用继承(子类化)时,该子类的行为(而不是属性)与超类不同


另一方面,为ProcessWatcher创建接口被广泛认为是使应用程序更加灵活的好方法。我引用《代码完整》作为我的参考。虽然我通常不会与McConnell争论,但我认为我需要一个重要的论据来说明这如何使应用程序更加灵活。如果到时候我们需要一个具有类似函数的第二个类,那么我会看到抽象类/接口,但不是在此之前。顺便说一句:如果你有这个参数,请务必在这里输入答案,因为我很想看到它!如果你有参考资料,也可以在cc2e.com网站上找到。我来这里是为了学习和教学,所以我不介意被证明是错的。-1因为你在第二段中说“是一个具体的例子”。“说明符”