How do I avoid breaking the Liskov substitution principle with a class that implements multiple interfaces?

  • A+
Category:Languages

Given the following class:

class Example implements Interface1, Interface2{ ... } 

When I instantiate the class using interface1:

Interface1 example = new Example(); 

Then I can call only the Interface1 methods, and not the Interface2 methods, unless I cast:

((Interface2) example).someInterface2Method(); 

Of course, to make this runtime safe, I should also wrap this with an instanceof check:

if (example instanceof Interface2) {     ((Interface2) example).someInterface2Method(); } 

I'm aware that I could have a wrapper interface that extends both interfaces, but then I could end up with multiple interfaces to cater for all the possible permutations of interfaces that can be implemented by the same class. The Interfaces in question do not naturally extend one another so inheritance also seems wrong.

Does the instanceof / cast approach break LSP as I am interrogating the runtime instance to determine its implementations? Whichever implementation I use seems to have some side-effect either in bad design or usage.

 


I'm aware that I could have a wrapper interface that extends both interfaces, but then I could end up with multiple interfaces to cater for all the possible permutations of interfaces that can be implemented by the same class

I suspect that if you're finding that lots of your classes implement different combinations of interfaces then either: your concrete classes are doing too much; or (less likely) your interfaces are too small and too specialised, to the point of being useless individually.

If you have good reason for some code to require something that is both a Interface1 and a Interface2 then absolutely go ahead and make a combined version that extends both. If you struggle to think of an appropriate name for this (no, not FooAndBar) then that's an indicator that your design is wrong.

Absolutely do not rely on casting anything. It should only be used as a last resort and usually only for very specific problems (e.g. serialization).

My favourite and most-used design pattern is the decorator pattern as such most of my classes will only ever implement one interface (except for more generic interfaces such as Comparable). I would say that if your classes are frequently/always implementing more than one interface then that's a code smell.


If you're instantiating the object and using it within the same scope then you should just be writing

Example example = new Example(); 

Just so it's clear (I'm not sure if this is what you were suggesting), under no circumstances should you ever be writing anything like this:

Interface1 example = new Example(); if (example instanceof Interface2) {     ((Interface2) example).someInterface2Method(); } 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: