Reputation: 11851
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()")?
Upvotes: 4
Views: 563
Reputation: 91871
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.
Upvotes: 1
Reputation: 22914
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.
Upvotes: 1
Reputation: 12498
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.
Upvotes: 2
Reputation: 52310
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
}
}
Upvotes: 0
Reputation: 8526
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)
Upvotes: 3
Reputation: 9018
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?
Upvotes: 0
Reputation: 16383
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.
Upvotes: 0