多重继承是否违反单一责任原则?


18

如果您有一个从两个不同的类继承的类,这是否意味着您的子类自动(至少)自动做2件事,每个超类都做一件?

我相信,如果您有多个接口继承,也没有什么区别。

编辑:明确地说,我认为如果子类化多个类违反了SRP,则实现多个(非标记或基本接口(例如,可比较)接口)也违反了SRP。


明确地说,您还认为实现多个接口违反了SRP吗?

我相信,如果子类化多个类违反了SRP,则实现多个(非标记)接口也违反了SRP。
m3th0dman 2012年

我会赞成这个问题,但您已将您的意见嵌入该问题,我不同意。
妮可·

1
@NickC:我没有发表我的意见(您应该已经阅读了上面的评论);我将编辑问题以使其更清楚。
m3th0dman'8

1
@NickC我没有意见,这就是为什么我问。我只说了两者是相关的(接口继承和类继承)。如果它违反了类继承,那么它也违反了接口继承,如果不是针对一个类的继承,那么也不会违反另一个。而且我不在乎上投票...
m3th0dman 2012年

Answers:


17

从狭义上讲,答案是“是”:假设您的基类或接口是为单一目的而设计的,则继承它们两者的确会创建一个具有多个职责的类。但是,是否“不好”取决于您继承的类或接口的性质。

您可以将类和接口划分为两个主要的组-解决系统基本复杂性的组和解决系统意外复杂性的组。如果从多个“基本复杂性”类继承,那就不好了。如果您从一个“基本”类和一个或多个“偶然”类继承,则可以。

例如,在开票系统中,您可以具有用于表示发票和开票周期的类(它们可以解决基本的复杂性),以及用于持久化对象的类(可以解决意外的复杂性)。如果你这样继承

class BillingCycleInvoice : public BillingCycle, public Invoice {
};

这很不好:您BillingCycleInvoice负有混合的责任,因为这与系统的基本复杂性有关。

另一方面,如果您这样继承

class PersistentInvoice : public Invoice, public PersistentObject {
};

您的课程没问题:从技术上讲,它可以同时处理两个问题,但是由于只有一个是必不可少的,因此您可以注销继承意外事件作为“经商成本”。


3
您的第二个示例非常类似于面向方面的编程中的一个横切关注点。这就是说,您的对象有时需要执行的操作(例如日志记录,访问控制测试或持久化)不是其核心重点,并且您可以通过多重继承来完成。这是该工具的适当用法。

最简单的方法是:如果要实现新接口需要完成类功能,则不需要。但是,如果它与其他类一起增加了新的责任,Implement接口,则注入它作为依赖将永远不会违反SRP
Ramankingdom

9

SRP是避免糟糕的上课的准则,但它也可以从字面上理解,项目开始时会产生大量的上班时间,如果没有少数几个步骤的结合,它们实际上是无能为力的。多个继承/多个接口可能是一个类变得太大的信号,但也可能表明您的注意力过于分散,无法解决当前的任务,并且您的解决方案设计过度,或者仅仅是一个完美的选择多重继承的有效用例,您的后顾之忧是没有根据的。

软件设计既是科学,又是艺术,它是许多竞争利益之间的平衡。我们有规则来帮助避免我们所知道的事情会在一个方向上引起问题,但是这些规则可以很容易地将我们带到与我们一开始就想避免的事情一样糟糕或更糟的地方。


4

有些。让我们关注SRP的主要原理:

一堂课只有一个改变的理由。

多重继承不会强制这样做,但会导致这种情况。如果该类重写或实现了其基类,则往往是更改它的更多原因。这样,接口多重继承往往比类继承更麻烦。如果两个类被继承但未被覆盖,则更改的原因存在于基类中而不是新类中。

多重继承不违反SRP的地方是,除了一种基本类型之外,其他所有类型都不是该类正在实现的东西,而是充当该类恰好具有的特征。IDisposable在C#中考虑。一次性的东西没有两个职责,界面只是充当共享特质但职责明显不同的类的视图。


2

我认为不是。对我来说,一个责任就是“为我的应用程序的用户建模”。我可能需要通过Web服务传递该数据,并将其存储在关系数据库中。我可以通过继承几个混合类来提供该功能。

这并不意味着班级要承担三项责任。这意味着对用户建模的部分责任需要支持序列化和持久性。


2

一点也不。在Java中,您可以有一个表示某种域对象的接口,例如Foo。它可能需要与其他Foo对象进行比较,因此实现了Comparable(在Comparator类中外部化了比较逻辑);该对象可能还需要可序列化,以便可以在网络上进行传输;并且可能需要克隆。因此,该类实现了三个接口,但是内部没有任何逻辑可以支持它们,而Foo则不支持。

也就是说,将SRP发挥到极致是愚蠢的。如果一个类定义了多个方法,是否违反了SRP?所有Java对象都有一个toString()方法和一个equals(Object)方法,这意味着Java中的每个对象都负责相等性和自表示。那是一件坏事?


1

我想这取决于您如何定义责任。在经典的iostream示例中,它不违反SRP。IOstream负责管理一个双向流。

用尽原始职责后,您将转而使用更通用的高级职责,毕竟如何定义主要切入点的职责?它的责任必须是“成为主要切入点”,而不是“我的应用程序所要做的一切”,否则就不可能不违反SRP并生成应用程序。

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.