23

If you have a class which inherits from two distinct classes, does not this mean that your subclass automatically does (at least) 2 things, one from each superclass?

I believe there is no difference if you have multiple interface inheritance.

To be clear, I believe that if subclassing multiple classes violates SRP, then implementing multiple (non-marker or basic interface (e.g. Comparable)) interfaces violates SRP too.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
Random42
  • 10,370
  • 10
  • 48
  • 65
  • Just to be clear, you also believe implementing multiple interfaces violates the SRP? –  Aug 07 '12 at 16:44
  • I believe that if subclassing multiple classes violates SRP, then implementing multiple (non-marker) interfaces violates SRP too. – Random42 Aug 07 '12 at 17:56
  • I would upvote this question, but you've embedded your opinion in the question, which I don't agree with. – Nicole Aug 07 '12 at 18:38
  • 1
    @NickC: I have not said my opinion (you should have read the above comment); I will edit the question to make it more clear. – Random42 Aug 08 '12 at 06:00
  • @m3th0dman Ok, I guess I still feel like that is your opinion. Fair enough; it's your question. I just have a hard time voting up questions that seem to be loaded. – Nicole Aug 08 '12 at 06:35
  • 1
    @NickC I do not have an opinion, that's why I asked. I only said that the two are related (interface inheritance and class inheritance); if it violates for class inheritance then it violates for interface inheritance too, if it doesn't for one then neither does it violate for the other. And I do not care about the up vote... – Random42 Aug 08 '12 at 11:32
  • Breathing violates the Single Responsibility Principal. Just ignore it. Or, understand the original intent of SRP and ignore all the misinterpretations. – user949300 Nov 18 '21 at 19:41
  • 3
    The single responsibility principle does **not** say that a class cannot do two or more things. A class can do as many things as you want as long as they are related to the same business requirement. – JacquesB Nov 19 '21 at 19:55
  • I think "one level of abstraction" is a more helpful way of understanding SRP. I think when having a class dealing with reading and writing to the file system it could inherit `Reader` and `Writer` interfaces and the level of abstraction would be "dealing with the filesystem". And I would not say that this class violates SRP because it does both "reading" and "writing". – Thomas Junk Nov 22 '21 at 17:10

7 Answers7

20

In a very narrow sense, the answer is "Yes": assuming that your base classes or interfaces are designed for a single purpose, inheriting both of them does create a class with multiple responsibilities. However, whether or not it is "a bad thing" depends on the nature of the classes or interfaces that you are inheriting.

You can partition your classes and interfaces into two major groups - the ones addressing the essential complexity of your system, and the ones addressing its accidental complexity. If you inherit from more than one "essential complexity" classes, it is bad; if you inherit from one "essential" and one or more "accidental" classes, it is OK.

For example, in a billing system you could have classes for representing invoices and billing cycles (they address the essential complexity) and classes for persisting objects (they address the accidental complexity). If you inherit like this

class BillingCycleInvoice : public BillingCycle, public Invoice {
};

it is bad: your BillingCycleInvoice has a mixed responsibility as it relates to the essential complexity of the system.

On the other hand, if you inherit like this

class PersistentInvoice : public Invoice, public PersistentObject {
};

your class is OK: technically, it services two concerns at once, but since only one of them is essential, you can write off inheriting the accidental one as the "cost of doing business".

Sergey Kalinichenko
  • 17,393
  • 4
  • 57
  • 73
  • 5
    Your second example is very similar to what would be a cross-cutting concern in aspect-oriented programming. This is saying that your objects sometimes need to do things (like logging, access control tests, or persisting) that aren't their core focus, and that you can do that with multiple inheritance. That's an appropriate use of the tool. –  Aug 08 '12 at 08:08
  • The Simplest is If implementing a new interface requires to complete the class functionality then its not. But if its adding new responsibility Implement interface with some other class then inject as dependency will never violate SRP – Ramankingdom Nov 16 '17 at 07:17
11

The SRP is a guideline to avoid god-classes, which are bad, but it also can be taken too literally and a project starts balloon with tons of classes that can't really do anything without a handful being combined. Multiple inheritance/multiple interfaces can be a sign a class is getting too big, but it could also be a sign that your focus is far too granular for the task at hand and your solution is over-engineered, or it could simply be a perfectly valid use case for multiple inheritance and your worries are unfounded.

Software design is as much art as science, its a balancing act of many competing interests. We have rules to help avoid things we know are to far in one direction that cause problems, but those rules can just as easily take us to a place that is just as bad or worse than what we were trying to avoid in the first place.

Ryathal
  • 13,317
  • 1
  • 33
  • 48
4

Somewhat. Let's focus on the main principle for SRP:

A class should only have one reason to change.

Multiple inheritance doesn't force this, but tends to lead to it. If the class overrides or implements its base classes, that tends to be more reasons for it to change. In this way, interface multiple inheritance tends to be more troublesome than class inheritance. If two classes are inherited but not overridden, then the reasons to change exist in the base classes not the new class.

The places where multiple inheritance does not violate SRP is when all but one of the base types aren't something that the class is implementing, but act as a trait that the class happens to have. Consider IDisposable in C#. Things that are disposable don't have two responsibilities, the interface just acts as a view into classes that share the trait but have decidedly different responsibilities.

Telastyn
  • 108,850
  • 29
  • 239
  • 365
4

Not at all. In Java, you can have an interface that represents some sort of domain object--a Foo, for example. It may need to be compared to other Foo objects, and so it implements Comparable (with the comparison logic externalized in a Comparator class); it may be that this object also needs to be Serializable, so that it can be transported across the network; and it may need to be Cloneable. Thus the class implements three interfaces but does not have any logic within to support them beyond that supported by Foo.

That said, it's silly to take the SRP to extremes. If a class defines more than one method, is it violating the SRP? All Java Objects have a toString() method and an equals(Object) method, which means EVERY object in Java is responsible for both equality and self-representation. Is that a bad thing?

Matthew Flynn
  • 13,345
  • 2
  • 38
  • 57
2

Not in my opinion. To me, a single responsibility is "model a user of my application". I may need to deliver that data via a web service, and store it in a relational database. I could provide that functionality by inheriting a couple of mix-in classes.

That doesn't mean the class has three responsibilities. It means that part of the responsibility to model a user requires supporting serialization and persistence.

kevin cline
  • 33,608
  • 3
  • 71
  • 142
1

I guess it depends on how you define the responsibility. In the classic iostream example it doesn't violate the SRP. The IOstream is responsible for managing one bidirectional stream.

After you run out of primitive responsibilities you move on to more generic high level responsibilities, after all how do you define the responsibility of your main entry point? Its responsibility has to be 'be the main entry point' not 'everything my app does' otherwise it is impossible to not violate the SRP and produce an application.

stonemetal
  • 3,371
  • 16
  • 17
0

Not at all. Let’s say you have a button in the UI, and it’s responsibility is to start the process of deleting an address in the user’s address book.

The button also has the responsibility to process mouse clicks, to redraw itself when needed, change its appearance while highlighted, hide the background behind it, show or hide itself, change its Color or title as directed and so on. That’s at least a dozen responsibilities and violations of the dreaded “single responsibility principle”.

But that’s not how it works! Your button has one responsibility. Multiple inheritance has nothing to do with this.

gnasher729
  • 42,090
  • 4
  • 59
  • 119