2

This is a logical development of another question I asked.

Supposedly you have an interface, some methods of which might either be supported by a concrete implementation or not. The goal is to provide a reasonable way for the client to find out whether his particular implementation supports each particular method and to recover if it doesn't.

The solution I came up with utilizes the standard java.lang.UnsupportedOperationException, which is thrown by the concrete implementation if the method is unsupported:

public interface CommonInterface {
    void possiblyUnsupportedOperation () throws java.lang.UnsupportedOperationException;
}

However, this is claimed to be a bad solution, since the exception mechanism should not be used as a means of checking whether an operation is available. So the alternative suggestion is to use tester methods:

public interface CommonInterface {
    void possiblyUnsupportedOperation ();
    boolean isOperationSupported ();
}

But what if the interface has a whole multitude of optional operations? Should I use multiple tester functions? Should I create a separate Enum to map the optional methods onto and pass it as a method descriptor to a single tester function? Both variants look kinda clunky to me.

Is there an alternative way that is both an elegant code and a good design solution?

Community
  • 1
  • 1
Semisonic
  • 1,152
  • 8
  • 21
  • [Chain-of-responsibility pattern](https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern). – Elliott Frisch Feb 16 '17 at 02:01
  • Please read about the [interface segregation principle](https://en.wikipedia.org/wiki/Interface_segregation_principle) – fps Feb 16 '17 at 02:17
  • @FedericoPeraltaSchaffner just so that I understand you correctly. By suggesting using that principle, did you mean creating a base interface with all the methods supported for sure, then a separate interface for each optional method, and doing something like `if (baseObject instanceof OptionalInterface1) { OptionalInterface1 oi1Object = (OptionalInterface1)baseObject; }`? – Semisonic Feb 16 '17 at 12:41
  • @Semisonic I was suggesting there might be some flaw in your design. It seems to me that your `CommonInterface` interface has too many methods. Instead, I would have smaller interfaces (the so-called role interfaces). Then, a class should implement only the interfaces it needs to, and there wouldn't be any need to cast. (By the way, if you need to use `instanceof` too much, it is a code smell, IMO). – fps Feb 16 '17 at 12:51
  • @FedericoPeraltaSchaffner Well, in my case, I'm trying to build a wrapper API around a family of similar services that may, however, have custom functions pertaining to a particular service. These functions are of a helper nature, so they can be avoided, but if they are present then I'd still like to expose them to the client. That's why there's a multitude of optional methods - they don't belong to any segregated roles but are rather extensions of the same role which each service views a bit differently. My original question could be a source of context if it matters ;). – Semisonic Feb 16 '17 at 13:20
  • @Semisonic I see. Seems like you are *adapting* that family of similar services. Are you implementing the class that adapts these services, or are you just making the already implemented services implement your interface? – fps Feb 16 '17 at 15:33
  • @FedericoPeraltaSchaffner Well, what I do, in fact, is create the general wrapper interface through which _any_ service could be used, and I also create an implementation of that wrapper for at least one of those services (it's a Java wrapper around their web APIs). So my goal is to have an interface that would fit all the services and at the same time would allow for the tiny differences that the services' APIs have. – Semisonic Feb 16 '17 at 20:26

1 Answers1

0

If you own that interface you could extract a Parent interface with the methods that are always going to be implemented and inherit from that interface.

public interface ParentCommonInterface {
    void method1();
    void method2();
}

public interface CommonInterface extends ParentCommonInterface {
    void possiblyUnsupportedOperation();
}

class MyClass implements ParentCommonInterface {...}

If you don't own that interface you can create an Adapter class and use that one to declare the object.

public interface CommonInterface {

    void possiblyUnsupportedOperation();
        boolean isOperationSupported();
    }

    public class AdapterClassOne implements CommonInterface {
        void possiblyUnsupportedOperation() {...}
        boolean isOperationSupported() {return false;}
    }
}
alayor
  • 4,537
  • 6
  • 27
  • 47