How to pick action to execute based on objects instanceof? - java

I have some Implementations of class Base, and all objects are collected in a List<Base>.
How can I call a specific action based on the instanceof these objects, without having to use verbose instanceof checks? How could I pick a servicemethod to be executed based on the instance of these objects, but without having to care which object the action is executed on. The right service-method should be picked somehow automatically without typecasing or instanceof checks.
class Base;
class Foo extends Base;
class Bar extends Base;
class Service {
List<Base> bases;
public void someMethod() {
for (Base base : bases) {
//perform some instanceof dependend action.
//these actions cannot be inside of any Base class as it makes use of other objects too.
if (base instanceof Foo) {
fooService.action((Foo) base);
}
if (base instanceof Bar) {
barService.action((Bar) base);
}
}
}
}
//custom service methods
class FooService {
void action(Foo foo) {
}
}
class BarService {
void action(Bar bar) {
}
}

Polymorphism is one possibility. If the Base class contains an abstract action() method, you could call it directly, without any if statements.
Another is a registry. For each subclass of Base you could register a mapping to a service class. In someMethod(), look up the class in the registry, get the corresponding service class, and call it.
By the way, verbosity is not the only problem with the instanceof statements. Code you write with these can break as soon as a new subclass of Base is created. Satisfying the Open/Closed principle can result in less fragile code.

One possible solution is to use the Visitor pattern. You will need to combine FooService and BarService into a single class with both overloaded action() methods. Then you need to add a accept() method to each of the Foo and Bar classes which then can call the appropriate action() method. For more details see http://en.wikipedia.org/wiki/Visitor_pattern.
There are possibly other, more appropriate design patterns which can solve this problem. I suggest you study up on them.

The closest I ever got to solve this problem is:
class Base{};
class Foo extends Base{};
class Boo extends Base{};
Additional BaseService interface so every service class use the same methods:
public interface BaseService<T extends Base> {
void action(T base);
}
BooService:
public class BooService implements BaseService<Boo> {
public void action(Boo boo){
System.out.println("Action performed by BooService");
}
}
FooService:
public class FooService implements BaseService<Foo> {
public void action(Foo foo){
System.out.println("Action performed by FooService");
}
}
Additional ServiceSupplier class that will invoke proper Service base on passed object:
public class ServiceSupplier {
private Map<Class<? extends Base>, BaseService> services;
public ServiceSupplier(){
initializeServiceMap();
}
public BaseService getServiceOfType(Class<? extends Base> clazz){
return services.get(clazz);
}
private void initializeServiceMap() {
services = new HashMap<>();
services.put(Foo.class, new FooService());
services.put(Boo.class, new BooService());
}
}
And your Service class:
public class Service {
List<Base> bases;
ServiceSupplier serviceSupplier;
public Service(){
serviceSupplier = new ServiceSupplier();
bases = new ArrayList<>(Arrays.asList(new Foo(), new Boo()));
}
public void someMethod() {
bases.forEach(base -> serviceSupplier.getServiceOfType(base.getClass()).action(base));
}
}
May seem much as just for removing few "if" statements but having more services all you need to do is add them to initializeServiceMap() method.

Related

Does java support "Soft" interfaces?

Consider the following scenario:
Say that you created an interface Foo:
public interface Foo {
public void bar();
}
And say that there is an old class SomeOldClass in a certain library that you want to use. It already has the bar() method, but does not explicitly implement Foo.
You have written the following code for all classed that implement Foo:
public <T extends Foo> T callBarOnThird(List<T> fooList){
return fooList.get(2).bar();
}
And now you want it to also work for SomeOldClass. You dont have access to the source code of this class, so you can't modify it.
Is there a way to declare Foo or something similar as some sort of "soft" interface, (as in where any class that implements all the required methods would be accepted as an implicit implementation of the soft interface)? If not, how would you solve this with code that is as clean as possible?
No, it does not.
You have to provide an adapter instance (there are several methods and tools to help with that, but Java does not do it "implicitly").
Java is statically typed and dynamically bind.
Dynamically bind: This means that the linking between a method signature and its implementation happens at runtime. For example.
For example
public interface MyInterface {
void doStuff();
}
public class MyFirstImpl implements MyInterface {
#Override
public void doStuff() {
// do some stuff here
}
}
public class MySecondImpl implements MyInterface {
#Override
public void doStuff() {
// do some stuff here
}
}
So if you would have the next snippet
MyInterface test; // pointing to either MyFirstImpl or MySecondImpl
test.doStuff();
The JVM will determine at runtime weather to call the doStuff method from MyFirstImpl or MySecondImpl based on the runtime type of the object.
Statically typed: This means that the JVM will check at compile time weather a there is a method to call regardless of the implementation.
For example:
public interface MyInterface {
void doStuff();
}
public class MyFirstImpl implements MyInterface {
// no override here
public void doStuff() {
// do some stuff here
}
}
public class MySecondImpl implements MyInterface {
// no override here
public void doStuff() {
// do some stuff here
}
}
So if you would have the next snippet
MyInterface test; // pointing to either MyFirstImpl or MySecondImpl
test.doStuff();
The compiler will complain because it can't ensure at compile time that regardless of the implementation of MyInterface there is a doStuff method to call (although in this case, both implementations of MyInterface define a doStuff method).
This ensures that you won't get a NoSuchMethodException at runtime, if you would pass, for example, the next implementation.
public class MySecondImpl implements MyInterface {
// no override here
// no doStuff method
}
This adds some type safety to the language at the cost of some rigidity (since you are able to determine the issue earlier than at runtime and therefore you have a shorter feedback loop, at the cost of the scenario in which all the implementations actually expose the method not working out of the box).
How you should refactor your code:
Create a wrapper over the third party library and expose the interface from the wrapper.
public interface Foo {
void bar();
}
public class ThirdPartyFooWrapper implements Foo {
private SomeOldClass oldClass;
public ThordPartyFooWrapper (SomeOldClass oldClass){
this.oldClass = oldClass;
}
#Override
public void bar() {
this.oldClass.bar();
}
}
Then, in your code use ThirdPartyFooWrapper instead of SomeOldClass.
Hope this answers your question!
Extension to Thilos answer.
You can also use the decorator to handle this
public <T extends Foo> T callBarOnThird(List<T> fooList){
return new BarDecorator(fooList.get(2)).bar();
}
Inside the decorator, you can check if given Object is the instance of Foo or not then do operations accordingly.

Can interface methods be overloaded?

I'm trying to achieve an overloaded interface method. I know that this does not work in Java, but how could I rewrite the following to have the implementation type in my action() methods, and not the Base type?
class Base;
class Foo extends Base;
class Bar extends Base;
interface IService {
void action(Base base);
}
class FooService implements IService {
void action(Foo foo) {
//executes specific foo action
}
}
class BarService implements IService {
void action(Bar bar) {
//executes specific Bar action
}
}
usage:
Base base; //may be foo or bar
anyService.action(bar);
You get the idea. How could I do this?
Define an interface that both Foo and Bar should implement, so you can do like:
interface Actionable{
public void action;
}
class Base;
class Foo extends Base implements Actionable;
class Bar extends Base implements Actionable;
interface IService {
void action(Actionable a);
}
class FooService implements IService {
void action(Actionable a) {
...
}
}
class BarService implements IService {
void action(Actionable a) {
...
}
}
Anyway interfaces should make your code more robust and reusable - if you are looking into hacks to make them work, consider designing your application better.
This is not supported in Java and you are violating the OOP rules.
Depending on your intended usage, there are multiple things to try.
If your calls to the IService know which kinds of object they can take, you could try generics.
interface IService<T extends Base> {
void action(T foo)
}
and usage:
IService<Foo> fooService = ...
fooService.action(fooObject);
If that's not the case, you could have some check in your ´Base´ class to allow differentiation for your IService interface.
class Base {
boolean acceptsFoo();
boolean acceptsBar();
}
and you could use it like:
class AnyService implements IService {
void action(Base base) {
if (base.acceptsFoo()) {
((FooService) base).foo();
}
}
However, this seems like a strange design. An interface is aimed at providing uniform access, and if you need to differentiate between the arguments, this is almost always a sign of an interface that can be split up into several parts...
You can always typecast to a specific type to execute that action.
void action(Base base)
{
if(base instanceof Foo)
{
Foo foo = (Foo) base;
//executes specific foo action
}
else
{
// handle the edge case where the wrong type was sent to you
}
}
any way if you are passing objects of sub class
then behavior (instance methods) will be called of object(subclass) passed(polymorphism)
ie.overloaded method

Can you automatically cast an object of one class to a subclass and call an overloaded method in Java?

I have the following setup:
class Base {};
class ImplA extends Base {};
class ImplB extends Base {};
class ImplC extends Base {};
Base baseFactory(int type) {
switch(type) {
case 0:
return new ImplA();
case 1:
return new ImplB();
case 2:
return new ImplC();
}
Base a = baseFactory(0);
Base b = baseFactory(1);
Base c = baseFactory(2);
List<Base> list = new ArrayList<Base>();
list.add(a);
list.add(b);
list.add(c);
// Somewhere else I have:
interface BaseHandler {
process(ImplA a);
process(ImplB b);
process(ImplC c);
};
Now, what I would like to be able to do is something along the lines of:
class Processor {
BaseHandler bh;
Processor(BaseHandler bh) {
this.bh = b;
}
void processList(List<Base> list) {
for (Base x : list) {
bh.process(x);
}
}
And then have a user implement BaseHandler and be able to construct a Processor to operate on each element in the Base list.
But, this does not work as process(Base) is not defined. It may seem simple to just add 3 if statements, but I already have a switch like structure in building instances of classes extending the Base. It seems unnecessary to repeat this over and over. Is there a way to achieve this idea without writing an intermediate step that determines the runtime class of each Base in the list and calls the appropriate method (in effect another switch case -- but it would be if's)?
I think one work around idea would be to make each Base have an abstract process method which needs to be implemented by the Impl classes. However, this is not acceptable in my situation since the user will not be implementing the Impl classes. Basically, I need process to be a user-defined callback. Further, it does not make sense for process to be a member of the Impl or Base classes since it is in no way related. It's a separate callback that needs to respond dynamically to the type it is called with. And the type is always guaranteed to be a subclass of Base.
You do need the "intermediate step" that you describe, but it need not be if statements. What you're looking for is double dispatch using the visitor pattern. Basically your Base class would have a method:
void accept(BaseHandler handler);
and each subclass would implement it as:
handler.process(this);
where this would resolve to the correct type in each subclass at compile-time.
What you're looking for is the Visitor pattern. You put an abstract method on Base, but all it does is call the appropriate method in BaseHandler:
public interface Base {
void acceptHandler(BaseHandler handler);
}
Then your concrete implementations override acceptHandler and call the correct overload.
public class ImplA implements Base {
public void acceptHandler(BaseHandler handler) {
handler.process(this);
}
}
At this point there's not much value in the overloading, and you'd be better off just giving your methods descriptive names.
It sounds like what you want is the Visitor pattern here:
public interface BaseVisitor {
void caseA(ImplA a);
void caseB(ImplB b);
void caseC(ImplC c);
}
public class MyVisitor implements BaseVisitor {
void visit(List<Base> bases) {
for (Base b : bases) {
b.accept(this);
}
}
public void caseA(ImplA a) { // ... }
public void caseB(ImplB b) { // ... }
public void caseC(ImplC c) { // ... }
}
public abstract class Base {
abstract void accept(BaseVisitor visitor);
}
public class ImplA {
public void accept(BaseVisitor visitor) {
visitor.caseA(this);
}
}
public class ImplB {
public void accept(BaseVisitor visitor) {
visitor.caseB(this);
}
}
public class ImplC {
public void accept(BaseVisitor visitor) {
visitor.caseC(this);
}
}

How to use java interfaces with multiple implementing classes

public interface Foo {
}
public class SpecificFoo implements Foo {
}
public interface SomeInterface {
void thisMethod(Foo someKindOfFoo);
}
public class SomeClass implements SomeInterface {
public void thisMethod(Foo someKindOfFoo) {
// calling code goes into this function
System.out.println("Dont go here please");
}
public void thisMethod(SpecificFoo specificFoo) {
// not into this function
System.out.println("Go here please");
}
}
public class SomeOlderClass {
public SomeOlderClass( SomeInterface inInterface ) {
SpecificFoo myFoo = new SpecificFoo();
inInterface.thisMethod(myFoo);
}
}
calling code:
SomeClass myClass = new SomeClass();
SomeOlderClass olderClass = new SomeOlderClass(myClass);
I have an interface (SomeInterface) that several classes call into (such as SomeOlderClass). I have a class that implements the interface, but I want to do type safe operations on the specific implementations that are passed into the generic interface.
As shown in the above code, I really want to able to make another method that matches the specific type passed in to the interface. This doesn't work. I assume it is because the calling code only knows about the interface, and not the implementation with the more specific methods (even though SpecificFoo implements Foo)
So how can I do this in the most elegant way? I can get the code working by adding an if statement in the class implementing the interface (SomeClass):
public void thisMethod(Foo someKindOfFoo) {
// calling code goes into this function
if ( someKindOfFoo.getClass().equals(SpecificFoo.class) )
thisMethod(SpecificFoo.class.cast(someKindOfFoo));
else
System.out.println("Dont go here please");
}
However, this is not elegant, as I have to add if statements everytime I add a new kind of Foo. And I might forget to do so.
The other option is to add SpecificFoo to the SomeInterface, and let the compiler sort out reminding me that I need implementations in SomeClass. The problem with this is that I end up adding quite a bit of boiler plate code. (If someone else implements the interface, they have to implement the new method, as well as any tests)
It seems that there should be another option I am missing, given that Foo and SpecificFoo are related. Ideas?
MORE INFO:
Well I actually worked for a while to try and simplify the question. As I add more details the complexity goes up by quite a bit. But whatever... I think I can explain it.
Basically, I am write a GWT web apps RPC servlet using the command pattern as explained by Ray Ryan in his talk
There are several implementations of it on google code, but many of them suffer this inherit problem. I thought it was a bug in the GWT-RPC code bugreport HOWEVER, as I was implementing further I noticed a similar problem happening purely on the client side, and while in hosted mode. (ie all java, no gwt javascript madness).
So I abstracted the basic ideas to a raw java command line case, and saw the same issue, as described above.
If you follow along with what Ray Ryan discusses, Foo is an Action, SpecificFoo is a specific action I want to call. SomeInterface is the client side RPC service and SomeClass is the server side RPC class. SomeOlderClass is a kind of rpc service that would know about cacheing and whatnot.
Obvious, right? Well as I said, I think all the GWT RPC nonsense just muddies up the waters on the base issue, which is why I tried to simplify it as best I could.
If you need to find out the actual type of an object at runtime, then the design is most probably wrong. That violates at least the Open Closed Principle and Dependency Inversion Principle.
(Because Java does not have multiple dispatch, the thisMethod(Foo)will be called instead of thisMethod(SpecificFoo). Double dispatch could be used to get around the language's limitations, but there might still be some design problem lurking there...)
Please give more information on what you are trying to accomplish. Right now the question does not provide enough information to come up with a right design.
A generic solution is that since the action depends on the runtime type of Foo, that method should be part of Foo so that its implementation can vary depending on Foo's type. So your example would be changed to something like below (possibly adding SomeInterface or other parameters to thisMethod()).
public interface Foo {
void thisMethod();
}
public class SpecificFoo implements Foo {
public void thisMethod() {
System.out.println("Go here please");
}
}
Try using double dispatch: Add a method to the Foo interface that is called by SomeClass#thisMethod. Then place the code in the implementation of this method.
public interface Foo {
public void thatMethod(SomeClass a);
public void thatMethod(SomeOlderClass a);
}
public class SomeClass implements SomeInterface {
public void thisMethod(Foo someKindOfFoo) {
someKindOfFoo.thatMethod(this);
}
}
Sorry, I find the problem description far too abstract to be able to make a recommendation. You clearly have a design issue because you generally should not need to check the type of interface. I will give it a go though... First, I need to make your problem more concrete for my small brain to understand. Instead of Foos, how about Birds?
public interface Bird {
}
public class Ostrich implements Bird {
}
public interface BirdManager {
void fly(Bird bird);
}
public class AdvancedBirdManager implements BirdManager {
public void fly(Bird bird) {
System.out.println("I am in the air. Yay!");
}
public void fly(Ostrich ostrich) {
System.out.println("Sigh... I can't fly.");
}
}
public class ZooSimulation {
public ZooSimulation(BirdManager birdManager) {
Ostrich ostrich = new Ostrich();
birdManager.fly(ostrich);
}
}
public static void main(String[] args) {
AdvancedBirdManager advancedBirdManager = new AdvancedBirdManager();
ZooSimulation zooSimulation = new ZooSimulation(advancedBirdManager);
}
Here, the Ostrich will declare "I am in the air. Yay!" which is not what we want.
OK, so, ignoring the fact that I am failing basic OO here, the problem is that the BirdManager will look for the least-specific method that matches the type that is passed in. So no matter what kind of bird I give it, it will always match fly(Bird). We can put some if checks in there, but as you add more types of birds, your design will degrade further. Here's the tough part - I have no idea if this makes sense within the context of your problem, but consider this refactoring where I move the logic from the manager into bird:
public interface Bird {
void fly();
}
public class BasicBird implements Bird {
public void fly() {
System.out.println("I am in the air. Yay!");
}
}
public class Ostrich implements Bird {
public void fly() {
System.out.println("Sigh... I can't fly.");
}
}
public interface BirdManager {
void fly(Bird bird);
}
public class AdvancedBirdManager implements BirdManager {
public void fly(Bird bird) {
bird.fly();
}
}
public class ZooSimulation {
public ZooSimulation(BirdManager birdManager) {
Ostrich ostrich = new Ostrich();
birdManager.fly(ostrich);
}
}
public static void main(String[] args) {
AdvancedBirdManager advancedBirdManager = new AdvancedBirdManager();
ZooSimulation zooSimulation = new ZooSimulation(advancedBirdManager);
}
Our Ostrich now says the correct thing and the bird manager still treats it as just a bird. Again, bad OO (Ostriches should not have fly() methods) but it illustrates my thoughts.
As long as there are not too many implementations of Foo, I would declare an abstract method in SomeInterface for each subclass of Foo, and have an abstract class forward calls to a default method that is defined for the most general type:
public interface Foo {
}
public class SpecificFoo implements Foo {
}
public interface SomeInterface {
void thisMethod(Foo someKindOfFoo);
void thisMethod(SpecificFoo specificFoo);
void thisMethod(OtherSpecificFoo otherSpecificFoo);
}
public abstract class AbstractSomeInterface {
public void thisMethod(Foo wrongFoo) {
throw new IllegalArgumentException("Wrong kind of Foo!");
}
public void thisMethod(SpecificFoo specificFoo) {
this.thisMethod((Foo) specificFoo);
}
public void thisMethod(OtherSpecificFoo otherSpecificFoo) {
this.thisMethod((Foo) specificFoo);
}
}
public class SomeClass extends AbstractSomeInterface {
public void thisMethod(SpecificFoo specificFoo) {
// calling code goes into this function
System.out.println("Go here please");
}
}
public class SomeOlderClass {
public SomeOlderClass( SomeInterface inInterface ) {
SpecificFoo myFoo = new SpecificFoo();
inInterface.thisMethod(myFoo);
}
}

Extending functionality of all implementations of an Interface?

I'm looking to create a set of functions which all implementations of a certain Interface can be extended to use. My question is whether there's a way to do this without using a proxy or manually extending each implementation of the interface?
My initial idea was to see if it was possible to use generics; using a parameterized type as the super type of my implementation...
public class NewFunctionality<T extends OldFunctionality> extends T {
//...
}
...but this is illegal. I don't exactly know why this is illegal, but it does sort of feel right that it is (probably because T could itself be an interface rather than an implementation).
Are there any other ways to achieve what I'm trying to do?
EDIT One example of something I might want to do is to extend java.util.List... Using my dodgy, illegal syntax:
public class FilterByType<T extends List> extends T {
public void retainAll(Class<?> c) {
//..
}
public void removeAll(Class<?> c) {
//..
}
}
You can achieve something like this using a programming pattern known as a 'decorator' (although if the interface is large then unfortunately this is a bit verbose to implement in Java because you need to write single-line implementations of every method in the interface):
public class FilterByType<T> implements List<T> {
private List<T> _list;
public FilterByType(List<T> list) {
this._list = list;
}
public void retainAll(Class<?> c) {
//..
}
public void removeAll(Class<?> c) {
//..
}
// Implement List<T> interface:
public boolean add(T element) {
return _list.add(element);
}
public void add(int index, T element) {
_list.add(index, element);
}
// etc...
}
Alternatively, if the methods don't need to access protected members, then static helper methods are a less clucky alternative:
public class FilterUtils {
public static void retainAll(List<T> list, Class<?> c) {
//..
}
public static void removeAll(List<T> list, Class<?> c) {
//..
}
}
What prevents you from just adding new methods to the interface?
If you can't just add the new functionality to old interface, you could consider making another interface and then an implementation which merely implements those two. Just to be clear, in code this is what I mean:
// Old functionality:
public interface Traveling {
void walk();
}
// Old implementation:
public class Person implements Traveling {
void walk() { System.out.println("I'm walking!"); }
}
// New functionality:
public interface FastTraveling {
void run();
void fly();
}
// New implementation, option #1:
public class SuperHero extends Person implements FastTraveling {
void run() { System.out.println("Zoooom!"); }
void fly() { System.out.println("To the skies!"); }
}
// New implementation, option #2:
public class SuperHero implements Traveling, FastTraveling {
void walk() { System.out.println("I'm walking!"); }
void run() { System.out.println("Zoooom!"); }
void fly() { System.out.println("To the skies!"); }
}
I think it's illegal because you can not guarantee what class T will be. Also there are technical obstacles (parent's class name must be written in bytecode, but Generics information get lost in bytecode).
You can use Decorator pattern like this:
class ListDecorator implements List {
private List decoratingList;
public ListDecorator(List decoratingList){
this.decoratingList = decoratingList;
}
public add(){
decoratingList.add();
}
...
}
class FilterByArrayList extends ListDecorator {
public FilterByAbstractList () {
super(new ArrayList());
}
}
There is a delegation/mixin framework that allows a form of this. You can define a new interface, implement a default implementation of that interface, then request classes which implement that interface but subclass from elsewhere in your hierarchy.
It's called mixins for Java, and there's a webcast right there that demonstrates it.
I'm afraid it's not clear what do you want to get.
Basically, I don't see any benefit in using 'public class NewFunctionality<T extends OldFunctionality> extends T' in comparison with 'public class NewFunctionality extends OldFunctionality' ('public class FilterByType<T extends List> extends T' vs 'public class FilterByType<T> implements List<T>')

Categories

Resources