tags:

views:

113

answers:

8

Continuing from this question: http://stackoverflow.com/questions/1600667/method-overriding-and-visibility-in-java

I need to create class B that is almost identical to class A, except that B cannot do certain things that A can.

Being a lazy programmer as I am, I tried to inherit A, only to greet with error that B cannot reduce the visibility of A methods. Duh!..

Now A is an API from a vendor, my intention is to encapsulate this API so that it is easier to use.

I wonder what is the best practice to work around this?

+1  A: 

You can build a wrapper class offering a reduced API, or you can throw an exception like UnsupportedOperationException from the methods that you want to disable.

rsp
Please don't abuse `IllegalStateException`. There is no state involved here.
Grodriguez
@Grodriguez, offered another option, the actual choice of exception is up to the application model of course, and could opt for a state exception imho.
rsp
According to the documentation, the `IllegalStateException` "signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation." This is obviously misleading as the disabled methods are meant to throw the exception always, not depending on the application state or on the timing of the call.
Grodriguez
@Grodriguez, I have seen the use of `IllegalStateException` in situations where the classes represent states in a model, where the methods are called through an interface reference, making its use a valid one. As we don't know the context of the OP, I didn't want to assume his situation is different.
rsp
That would be reasonable, but it doesn't seem to be the case for the OP, since what he originally was trying to do was to *"reduce the visibility of certain methods"*. This isn't allowed in Java, but if it was allowed, obviously it would not depend on any application state. Edit: I see you already changed that to `UnsupportedOperationException`.
Grodriguez
+2  A: 

If B can't do all thing A can, you couldn't treat B as an A.

Maybe you need a wrapper, not a subclasse.

EDIT:

So you'd understand you'll never reduce the "visibility" of a subclass method :). Throw an exception or do nothing is not reduce the visibility, therefore you need a wrapper. Sometimes, this situation is a signal of a bad design (only sometimes).

This is very related to circle-ellipse problem.

Sinuhe
@Sinuhe yes I understand that OO concept alright.. I am just interested to know how others solve this problem.
Rosdi
+3  A: 

A facade is used when one wants an easier or simpler interface to work with.

You would have to create your own wrapper class (Facade Pattern) around your foreign interface.

interface Foreign
{
    void dontWantThis();
    void keepThis();
}

interface/class MyForeign
{
    void keepThis();
}

The implementation would then have a instance of Foreign that it can refer calls to.

willcodejavaforfood
Your suggestion is OK, but this is not a Facade.
Grodriguez
@Grodriguez - From wikipedia: A facade is an object that provides a simplified interface to a larger body of code, such as a class library.
willcodejavaforfood
Indeed. The intent of the Facade pattern is to "provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use." [GoF, p185]. This is not the case in this example; `MyForeign` is not providing a "simplified interface" to a "complex subsystem", it is just wrapping a single class. This is the Adapter / Wrapper pattern.
Grodriguez
@Grodriquez - I dont want to get dragged into a pointless discussion so lets just agree to disagree :)
willcodejavaforfood
@willcodejavaforfood: Agreed :)
Grodriguez
@Grodriquez - Pint now that we are friends? :)
willcodejavaforfood
Sure. Next time I go to London, or next time you come to Spain :)
Grodriguez
Awesome! I am going to Barcelona 31st of March.
willcodejavaforfood
That's a bit far from my place, but it may be nice :-)
Grodriguez
+1  A: 

The solution would probably use "composition" over "inhertence". You could have a property in class B, of type A. Then expose only those methods in B that you want to actually implement

madhurtanwani
This is a kind of a wrapper.
AntonioP
+5  A: 

Use Composition rather than Inheritance.

i.e. class B holds a reference to a class A and internally calls methods on it.

William
I will have to replicate all the methods in `A` that I _do_ want to expose into `B`, and there are lots of it!. Didn't I mention I am lazy? Lol..
Rosdi
Instead of `Lazy` be `Eager`
Shervin
A: 

Why would you do this? If the API is too big or complicated why dont you offer to fix it for the vendor, simplify it at the source?

AntonioP
+3  A: 

Two options:

If you need B to keep the same interface as A (so that client code can use any of the two without changes), you can override "forbidden" methods in B and have them throw an UnsupportedOperationException. For example:

public class A
{
    public int allowedMethod() { ... }
    public int forbiddenMethod() { ... }
}

public class B extends A
{
    public int forbiddenMethod()
    {
        throw new UnsupportedOperationException("Sorry, not allowed.");
    }
}

Or, if you really want the API of B to be a subset of the API of A, then just have B contain an instance of A, and delegate method calls appropriately.

    public class A
    {
        public int allowedMethod() { ... }
        public int forbiddenMethod() { ... }
    }

    public class B
    {
        private A a;

        public int allowedMethod()
        {
            return a.allowedMethod();
        }
    }
Grodriguez
Downvoter, care to explain?
Grodriguez
@Grodriguez The second solution was pretty much what I had in mind in the first place.. but I will have to replicate all the wanted methods manually. First solution seems 'unclean' for me.. lots of clutter and unwanted code.
Rosdi
Yes, that's true. I guess that depending on what is the ratio of methods to be kept / methods to be rejected, one of the solutions might look "cleaner" than the other one. e.g. if you only want to forbid 2-3 methods out of 20, then A probably looks cleaner. If you only want to keep 2-3 methods out of 20, then B looks cleaner. But everything else being equal I also tend to prefer B over A.
Grodriguez
`UnsupportedOperationException` violates Liskov substitution...
Dan Vinton
Since the OP actually wanted to "reduce the visibility of (certain) inherited methods" in the first place, looks like "violating Liskov substitution" is implied in his specification, isn't it?
Grodriguez
A: 

I would use the adapter pattern. http://en.wikipedia.org/wiki/Adapter_pattern

punkers