-3

I need to write a method which depends on the type we're passing as an argument. For instance:

public class A{
    void foo(Object o){
       if(o instanceof Integer){
           System.out.println("Integer");
       } 

       if(o instanceof Date){
           System.out.println("Date");
       }
}

   //And so forth
}

In my particular case the method has much more complex structure, but it doesn't matter here.

Of course if-then-else clauses are things that an object oriented program try to eliminate.

I think polymorhism can be help of here. But I have not realized how it can be helpful. Any suggestions?

UPD: I need to perform run-time type checking, therefore method overloading won't be helpful in that case.

UUPD:

I'm going to call the method in the following way:

Object o = null;

//Initializng the object, could be Integer, Date or String

A a = new A();

a.foo(o); //So I need to decide what to do from the run-time type of o
          //that's why overloading won't be helpful here.
St.Antario
  • 26,175
  • 41
  • 130
  • 318
  • 5
    The specific structure matters a lot. – chrylis -cautiouslyoptimistic- Apr 18 '15 at 16:37
  • @chrylis I think that this is a quite well-know problem. I just have not met them yet. Don't see how the specific structure can affect the solution in general? – St.Antario Apr 18 '15 at 16:38
  • Best would likely be multiple overloaded (not overridden) methods. – Hovercraft Full Of Eels Apr 18 '15 at 16:38
  • I believe Java supports method overloading. You can have multiple `foo()` functions declared, one for each type of argument. `foo(Integer o)`, and then `foo(Date o)` etc. – Havenard Apr 18 '15 at 16:38
  • @Havenard Of course it does, but it's compile-time things, not runtime. – St.Antario Apr 18 '15 at 16:39
  • Mayb you can use a marker interface to tag your supported class.Your custom classes can implement this interface or some sub interfaces. – Olli Zi Apr 18 '15 at 16:39
  • @HovercraftFullOfEels Overloading is about compile-time. But I need runtime type switching. – St.Antario Apr 18 '15 at 16:40
  • If you just want to print class name you can .getClass method , however if you want to some specific operatios the use method overloading as sugeected by @Havenard – Panther Apr 18 '15 at 16:40
  • 1
    @St.Antario: important restrictions should be part of your original question's text, not buried in comments. Please post all requirements so we can avoid having to painfully extract them in bits and pieces. – Hovercraft Full Of Eels Apr 18 '15 at 16:41
  • @HovercraftFullOfEels Well, I thought it would be clear from the question, because we all kno about method overloading. – St.Antario Apr 18 '15 at 16:41
  • 2
    Nothing is clear if it is not directly stated. If you have a clear restriction, again, please post it. – Hovercraft Full Of Eels Apr 18 '15 at 16:42
  • @St.Antario Yeah I understand your problem, you are using it as some sort of callback right? In this case I don't think you can run from it. I'm not an expert in Java, but maybe http://stackoverflow.com/a/5579385/156811 – Havenard Apr 18 '15 at 16:43
  • 1
    I still feel lost in this question. Perhaps you could benefit from a Visitor design pattern, but I can't say just yet, since the question seems ambiguous to me. Can you make it more concrete? – Hovercraft Full Of Eels Apr 18 '15 at 16:44
  • 1
    Still very unclear how your situation is. Can you modify the types sent in? Is it 5 or 500 types? What do you want to do exactly? What about a few type-specific overloads and then a fallthrough overload? – Jeroen Vannevel Apr 18 '15 at 16:45
  • possible duplicate of [switch instanceof?](http://stackoverflow.com/questions/5579309/switch-instanceof) – Havenard Apr 18 '15 at 16:48
  • Downvoters, please explain the reason so I could improve my question. – St.Antario Apr 18 '15 at 16:52
  • The question is unclear and seems too abstract. – Hovercraft Full Of Eels Apr 18 '15 at 16:56
  • @HovercraftFullOfEels What's unclear? – St.Antario Apr 18 '15 at 16:57
  • 1
    @St.Antario you've oversimplified the question. We don't know if Date and String are the actual types or if the actual types are types that you can change. Your example only prints the class name of the object, but we can only guess that it's not what you actually want to do (otherwise, you could simply use o.getClass().getSimpleName()). You haven't told us why your method absolutely needs to take Object as argument, and not some interface. Or how the objects are created before being passed to the method. We also don't know if we're talking about 3 or 50 types. Looks like an XY problem to me. – JB Nizet Apr 18 '15 at 17:01
  • @JBNizet Maybe so, but I expected that the types `Integer`, `Date` and some other sort of similar would be treated as built-in types. – St.Antario Apr 18 '15 at 17:42
  • Your question is now closed but hopefully one of the two answers have fully answered your question. If not, then you'll want to improve the question by giving more concrete information and code, improving the odds that the question will be re-opened. – Hovercraft Full Of Eels Apr 19 '15 at 00:16

2 Answers2

2

I think an abstract class can help you.

You can define something like

public abstract class Foo<A> {
  abstract void printText();
}

And then have specialized types like

public class IntFoo extends Foo<Integer> {

  private final int x;

  public IntFoo(final int x) {
    this.x = x;
  }

  @Override
  void printText() {
    System.out.println("Int is " + x);
  }
}

After that, you can execute your method with

public void foo(final Foo<?> fooInstance) {
   fooInstance.printText();
}

And call it with foo(new IntFoo(42)).

Martin Seeler
  • 6,874
  • 3
  • 33
  • 45
1

An idea I got:

public final class MatchType {

    private final Object obj;
    private boolean matched;

    private MatchType(Object obj) {
        this.obj = obj;
    }

    public static MatchType of(Object obj) {
        return new MatchType(obj);
    }

    public <T> MatchType on(Class<T> type, Consumer<T> action) {
        if (!matched && type.isInstance(obj)) {
            matched = true;
            @SuppressWarnings("unchecked")
            T t = (T) obj;
            action.accept(t);
        }
        return this;
    }

    public void onDefault(Consumer<Object> action) {
        if (!matched) {
            matched = true;
            action.accept(obj);
        }
    }
}

Now we could match the type of object:

MatchType.of(obj)
    .on(Integer.class, i -> System.out.println("Integer"))
    .on(String.class, s -> System.out.println("String"))
    .onDefault(o -> System.out.println("Something else"));
Bubletan
  • 3,833
  • 6
  • 25
  • 33