3

I've searched for answers here and every thread I found were in fact "fragments" of what I seek.

I'd like to find a better way than this :

~ EDIT: OOPS ! I meant to use primitive Wrapper classes in the first place, but I was thinking of using primitive types when calling the method at that very moment~ Thank you for noticing it :)

@Override
public void setValue(Object value) {

    if (value instanceof String) {

    } else if (value instanceof Integer) { // and not 'int'

    } else if (value instanceof Long) { // and not 'long'

    }
}

// The usage that made me confused in the first place :
int i = 42;
setValue(i);

Notice the @Override annotation: this is an implementation of an interface method. This method would accept different types based on the implementation so I don't want to create three disctinct methods using different parameter types.

In this example, this is a textbox that only accepts digits and nothing else, so it can only be represented by a String (which is validated by a Regular Expression ^[0-9]*$), a long and an int.

I'd also like it to - maybe, eventually - accept custom (and simple) DTO's that are more like POJOs, but if this particularity makes everything else complicated I've got something else in mind so don't worry too much about this one.

As I said, different implementations of this interface could accept totally different types.

* I am obviously not asking a way to switchcase Integers, Longs and String (which cannot be switchcased, yet. Not until Java7 that is), I want to switchcase the instanceofs *

After looking at

My implementation obviously works, but I just feel there's a better way. I am wondering if there is a cleaner method than doing what I did, what do you suggest and why?

Thank you for your time. Sincerely, Dominic Brissette.

EDIT: usage with primitive types and Autoboxing

public static void main(String[] args) {
    int i = 42;

    System.out.println(autoboxing(i));
}

public static boolean autoboxing(Object o) {
    return o instanceof Integer;
}

Outputs true because in the end, myInt instanceof Integer is kinda true ..!

Community
  • 1
  • 1
dominicbri7
  • 2,479
  • 4
  • 23
  • 33
  • 6
    How does your implementation "obviously" work? It gives me a compile-time error, as you can't use `instanceof` with primitive types... – Jon Skeet Jul 06 '11 at 13:27
  • For what it's worth, I think the code you have is the cleanest way to do it. (but compare with the boxed types, ie Integer, Long, Boolean etc, not int, long, boolean etc) – Bohemian Jul 06 '11 at 13:28
  • 3
    Objects are never primitives, so you can assume `Object instanceof primitiveType` is always false. – Peter Lawrey Jul 06 '11 at 13:29
  • Oops, of course I meant to use Wrappers (Integer, Long, etc.) since value is an OBJECT, my bad, I was just thinking about using this function with primitive values, due to Java autoboxing http://leepoint.net/notes-java/data/basic_types/autoboxing.html see my edit in a minute :) – dominicbri7 Jul 06 '11 at 14:06

3 Answers3

4

One thing you could do is wrap your primitive in an interface, and this way any value type implementing this interface could be passed as a value.

public interface ValueInterface {
    processValue();
}

Then the set value method would look like:

public void setValue(ValueInterface value) {
   value.processValue();
}

Now you're delegating the work to the actual object who knows how to act on itself.

Jeff Storey
  • 56,312
  • 72
  • 233
  • 406
  • Upvoted for pointing towards the path of Object-Orientation, happiness and enlightenment. – Adriaan Koster Jul 06 '11 at 13:54
  • @Adriaan haha it indeed makes us all very happy :D and stuff, and is a cleaner way, but isn't creating once again more and more interface and classes "too much" for such a simple need? And also the actual object can't just act on itself, its the implementation given in the example that has to act "on itself" (using sets and gets on member fields) using that value.. hmm the more I think about it the more confused I get :'( haha – dominicbri7 Jul 06 '11 at 14:19
  • Finally, I just decided to do setMutualValue(ValidatableDTO value); which is pretty much the same thing, and yes instead of delegating the "processing" to the value object, which I dont' really need since I only want to get() the value itself contained within the ValidatableDTO. I have no Idea why I wasted that much time when I could have done this since the very beginning, oh god, I hate mornings and feel stupid :'( everyone have a nice day! – dominicbri7 Jul 06 '11 at 14:44
  • I don't think this was _that_ stupid a question. It is worth it to reconsider typical scenarios now and then, even though it does not immediately pay off it makes you a better programmer in the long run. Whether the suggested interface is "too much" depends on the context of the code but in general I favor readable and clear object-oriented code over compact code full of shortcuts. The biggest cost of software is not in the writing but in the maintenance, often by other developers. – Adriaan Koster Jul 07 '11 at 07:39
2

Try Visitor pattern.

topchef
  • 19,091
  • 9
  • 63
  • 102
  • If I am not mistaken, is this pretty much the same as Jeff Storey's answer? If so see my comment :) Thank you for your time – dominicbri7 Jul 06 '11 at 14:21
  • No, with visitor you won't have to implement `ValueInterface` for each argument - you would need a visitor class that executes `processValue` for each type via double dispatch. – topchef Jul 06 '11 at 16:34
  • Visitor pattern for primitive types? How to implement `accept()` for `String` for example? – MariuszS Dec 29 '13 at 09:32
  • Thank you for your question: by extending `String` to implement interface with method `accept(IVisitor visitor)`. – topchef Dec 29 '13 at 18:47
1

Another way to handle this is to write code for any type of object.

private JLabel label;
@Override
public void setValue(Object value) {
    String text = value.toString();
    Long.parseLong(text); // to validate as a long value.
    label.setText(text);
}

The clean way to switch on type is to use overloading. Note: An Object cannot be a primitive.

public void setValue(String value) {

}

public void setValue(int value) { // shouldn't need this.

}

public void setValue(long value) {

}

It is highly likely you don't need a seperate int and long method as the later is likely to be enough.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • As I said in the description : "Notice the @Override annotation: this is an implementation of an interface method. This method would accept different types based on the implementation so I don't want to create three disctinct methods using different parameter types", but yes it is indeed a "clean way" but doesn't really apply to my situation as stated. :( – dominicbri7 Jul 06 '11 at 14:14
  • If you method really can take a generic object, which does it need to switch on type at all. Why not write code which works on any Object? What are you trying to do in each "switch" block? – Peter Lawrey Jul 06 '11 at 14:18
  • Since the value I want to set on my fields (one is a UI widget on which I want to setText(), and the other is a POJO on which I want to setValue()) and can only be a "digit-only" entity, I found that only these types could be successfully and directly translated to my value.... now I am thinking that it could be more like: if (isString || isLong || isInteger) setMyValues(value.toString) ????? what do you think of this? I kinda feel stupid and confused now – dominicbri7 Jul 06 '11 at 14:30
  • I have added an example where you don't need to know the original type, only what a valid entry looks like. – Peter Lawrey Jul 06 '11 at 15:03