tags:

views:

132

answers:

7

Is there a means to prevent a subclass from exposing public methods other than those defined in the base class, at compile-time?

For example:

abstract public class AClass {

   abstract public void anAllowedMethod();

}

public class BClass extends Aclass {

    public void anAllowedMethod() {

    }

    public void anAdditionalNonAllowedMethod() {

    }

    private void thisMethodIsAllowedBecauseItsNotPublic() {

    }

}

Perhaps there is some keyword I can use in AClass to declare the subclass can only implemented the methods defined in AClass (ie. "anAllowedMethod()")?

+3  A: 

Not really. When you define a class and say that it extends/implements another class it must adhere to the contract of the class it extends/implements. There is no restriction on containing the said class' behaviour further.

In a project I'm working on, some developers are adding extra methods to the subclass which are not necessary

As I see, this effectively means that your design is going to pieces due to developers doing what they please (by adding new public behaviour to objects).

Unfortunately, if you don't manage your design once it is in the implementation phase (coding) bad things are bound to happen. Please consider a process of review (automated/manual)

Ryan Fernandes
Very true
Joel
A: 

not in the general case...

But...

If you are trying to block specific interfaces, you could declare a final method in your abstract base class with the name of the method(s) from the interface. That wouldn't prevent anyone from making a sub-class implement the interface, but it would certainly prevent them from doing anything with the method calls.

I suppose that you could use reflection at runtime to disallow things...

And you could absolutely do this with an AOP container. I just saw additional comments on the OP, and I see now what you are going for. My recommendation is to treat this as something that should be managed at the source control level - either have a test mode that does runtime checks for the problem (i.e. treat this as an implementation unit test), or (if you are using a CI system) have this sort of thing tested at check-in.

Kevin Day
A: 

Have you considered final?

I know, it's not what you asked for, but there's no feature like this in the language. Or, for that matter, in any language I know - and I know a lot.

Which leads us to trying to find another way to do what you want to do - to meet the underlying need.

However, since I can't imagine a sensible reason to do this, I'm stumped.

Why do you want to prevent a subclass from adding methods? What is it that you fear will happen?

CPerkins
I don't think he would want to use final because he stil wants the sublcasses to define their own anOllowedMethod.
Taylor Leese
A: 

I agree with the others on the thread that what you are trying to do isn't desireable. However, I believe you could use reflection to make sure any methods declared are ones you are expecting.

Method[] methods = this.getClass().getMethods();
for (Method method : methods)
{
    if (method.getName() ... ) // check to make sure method is expected
    {
        .... // if method not expected throw an exception
    }
}
Taylor Leese
I wouldn't even suggest doing this ... for fear that someone might be silly enough to implement it!
Stephen C
Yeah, you're probably right, but it would do what he is asking. :-)
Taylor Leese
+2  A: 

You could make the class final so it can't be subclassed (can't be abstract, of course), but design it to use composition/delegation, so instead of varying implementation via subclasses, you vary it by what strategy objects you use in the composition of instances of the class.

Anon
+1  A: 

Java doesn't support this. However, if you want clients of your class to use only the interface you defined, you could declare a java interface and then use a factory to create objects that implement that interface. Therefore the clients could only call methods from the interface. Of course if someone is determined they could find ways around this (like doing an explicit cast), but if people are intentionally breaking your design, you have bigger problems to contend with.

Ken Liu
I personally think this is the (mostly) correct answer. With Java you really should be coding to interfaces anyway. However, rather than writing all the factories, the latest fad/trend is to create implementation classes using dependency injection (Spring, EJB3, Guice, etc.). And honestly, I find DI very, very easy to work with.
hohonuuli
Agree. Once you have lots of factories, using a DI framework is the next logical step, anyway.
Ken Liu
+1  A: 

At this stage of the game it is probably too late, but what you could do is create a final class with the relevant methods that takes a delegate in its constructor of a different type that has actual implementation, and have the methods of the final class call the delegate. That way whatever they add to the delegate won't be callable at all.

Yishai