Extend To Implement Interfaces

It is certainly a good technique to define separate interfaces for separate groups of clients, as RobertMartin has described in "The InterfaceSegregationPrinciple" in the August '96 issue of CppReport (http://www.sigs.com/publications/docs/cppr/9608/cppr9608.toc.html). Unfortunately, it sometimes happens that a useful class was already written without using this technique, and actually has many disparate methods, only some of which are meaningful for certain clients.

In Java, it turns out that you can remedy this situation without touching the original class - something very useful when that class is part of a commercial library.

All you need to do is define an interface which specifies only those methods of interest, and extend the original class to a subclass with no implementation - but which states that it implements the interface. The resultant class can then be passed to clients expecting your interface, thus effectively decoupling them from the library class.

For example:

   interface SoundPlayer {
       void play( URL url );
       }

public class MyApplet extends Applet implements SoundPlayer ...
Now MyApplet may be passed to a class that just wants to play sounds, without knowing about Applet.

-- RussellGold


Cool. A Facade done using interfaces.


Actually, I think this would be an adapter not a Facade


A few students of mine recently took this idiom off in a different, but interesting direction. They were programming with ObjectStore from ObjectDesign, an OODBMS that has a Java connection. Their problem was this -- they had many places in their code that used Vectors -- unfortunately ObjectStore requires that instead of using a Vector in a persistent class you must use a class they provide, called OSVector. This class implements all of the methods of Vector, but is not polymorphically substitutable for Vector. Well, my students didn't want to be hard-coding all of this database-dependent code into their domain classes; they might, after all, switch database vendors at some time.

So what they did was define a new interface (let's call it Vectorish). They then used ExtendToImplementInterfaces to make a subclass of Vector, which overrode no methods, and a subclass of OSVector, which overrode no methods, both of which implemented Vectorish. They then used UseFactoriesToBuildObjects to create instances of the appropriate subclass whenever they needed something. Very slick -- almost a use of the ShieldPattern.

KyleBrown


Very interesting approach. A while back I was very keen on InterfacesShouldBeAdjectives until I saw DontDistinguishBetweenClassesAndInterfaces. The argument against adjectival naming there was more or less that it introduces new abstraction and YouArentGonnaNeedIt. What we are seeing here is that something like "Vectorness" is an emergent abstraction that comes specifically from the fact that we don't care whether something is-a Vector all we care about is whether it behaves like one. This is particularly important in cases like the last one where different libraries are being used. In this sense, I see adjectival naming , which gets at the qualities and capabilities of classes of objects as more versatile than the traditional noun-based names. Sure enough, you can do the same work with a made up noun-phrase, but I find the adjectival phrases more appropriate although they do not sound natural yet (perhaps because of a lack of widespread use). -- MichaelFeathers


In RubyLanguage, the above workarounds are not needed, thanks to DuckTyping.


CategoryRefactoring, CategoryPattern


EditText of this page (last edited September 1, 2004) or FindPage with title or text search