Reputation: 2179
I have 3 classes.
public interface Operation {
void move();
void delete();
void search(String criteria);
}
public abstract class AbstractOperationProcessor implements Operation {
public void move() {
// some logic
}
}
public class DailyMailProcessor extends AbstractOperationProcessor{
// need to hide this method because I don't want to provide them to customer
public void delete() {}
public void search(String criteria) {}
}
What I need is to hide methods delete()
and search(String)
from API. How can I do it without changing interface Operation
and abstract class AbstractOperationProcessor
?
Upvotes: 4
Views: 7179
Reputation: 1561
You cannot do that. Every method declared in the interface should be implemented by the class. What you can do is you just implement those methods but do not give any definition to it.
Upvotes: 2
Reputation: 578
the best solution that handle your probleme, if, and only if you want to have it in an elegante way, is to use a component system and it would look some this like that:
abstract class Component {
abstract void perform();
}
abstract class Move extends Component {
void perform() { ... }
}
class AbstractOperationProcessor {
List<Component> components;
...
}
Upvotes: 0
Reputation: 3541
As the other answers already stated: You cannot hide a method of a superclass. There is also a good reason that you cannot do this: Polymorphism allows you to pass any object of a subtype where an object of a supertype is needed. In your case, if you have a method
void foo(Operation op){op.delete()}
you can call
foo(new DailyMailProcessor())
As you can see, foo does not know the exact type of op, but because delete is in Operation's interface, the method delete can be called.
If you happen to want to remove some methods from a subtype's interface, you are probably not implementing a behavioral subtype! I suggest you have a look at the Liskov Principle, which is one of the fundamental principles in object oriented programming.
If, what you have is not a behavioral subtype, you are wrongly trying to achieve code reuse by inheritance. You should use composition instead. Favor composition over inheritance (Item 16, Effective Java). The reason to favor composition in your case is obvious: You do not have to throw an UnsupportedOperationException (as mentioned in the other answers) and hereby gain static safety.
Edit: To clarify what I mean when telling you to use composition: Instead of having class DailyMailProcessor extending Operation, give it an member variable of type Operation and forward calls to the methods you want to support to the member variable.
public interface Operation {
void move();
void delete();
void search(String criteria);
}
public class DailyMailProcessor {
private Operation op;
public DailyMailProcessor {/*instantiate op*/}
void move() {op.move();}
}
Upvotes: 4
Reputation: 86774
You cannot. The best you can do is implement stubs that throw something like NotImplementedException
and document this fact.
I would use this as an opportunity to examine the definition of the top-level interface. If you need to hide some of its methods then the real problem may be that it aggregates unrelated functionality. You may need to split it into two separate interfaces.
Remember, you can "inherit" (i.e. implement) multiple interfaces.
Upvotes: 9
Reputation: 15709
Edit:
As suggested in the comments, UnsupportedOperationException
might be a better choice.
Original answer:
There is the IllegalStateException
just for that. Just make all the methods you don't want to implement throw that. Just do:
public class DailyMailProcessor extends AbstractOperationProcessor {
public void delete() {
throw new IllegalStateException();
}
public void search(String criteria) {
// do something useful here
}
}
Upvotes: 1