5

Code:

public void ifChangedString(String key, Consumer<String> consumer) {
    ...
    consumer.accept(getString(key));
}

public void ifChangedBoolean(String key, Consumer<Boolean> consumer) {
    ...
    consumer.accept(getBoolean(key));
}

Is it possible to make single method like public <T> void ifChanged(String key, Class<T> clazz, Consumer<T> consumer)?

Well obvious solution is public void ifChanged(String key, Consumer<Object> consumer) but I don't want to use Object as argument type, better to use several methods like above.

The problem is that for accept method I need ? super XXX and only super is Object. So is it possible at all?

Drunya
  • 121
  • 1
  • 7
  • Are `String` and `Boolean` the only options, or do you have some other methods in addition to `getString()` and `getBoolean()`? If `String` and `Boolean` are the only options, do you want a solution which enforces this at compile-time, or would a runtime check (throwing `IllegalArgumentException` when called with the wrong `clazz`) be sufficient? – kaya3 Jan 25 '20 at 17:57
  • What are you using the `String key` for? – Scratte Jan 25 '20 at 18:14
  • @Scratte updated code. – Drunya Jan 25 '20 at 18:27

3 Answers3

2

You can create generic method that accepts type T object and Consumer of type T

public <T> void ifChanged(T t, Consumer<T> consumer) {

    consumer.accept(t);

}

And you can call that method by passing any object with corresponding Consumer action

ifChanged("String", s->System.out.println(s.length()));
ifChanged(10, i->System.out.println(i.toString()));
Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
  • It's String key, not T value. I imagine the OP also needs `getValue(key) as T` to pass into the consumer. – charles-allen Jan 25 '20 at 16:23
  • It works only if method `accept` accepts function argument. And here I need to assign some value to `T` and it's impossible until `T` is super of whatever. I've updated my code. Or I'm missing something? – Drunya Jan 25 '20 at 16:25
  • sorry it is not really clear to me @Drunya so your are looking to make dynamic decision call of `getBoolean()` or `getString()` based on consumer type ? – Ryuzaki L Jan 25 '20 at 17:02
  • @Deadpool yes and consumer should then accept this type and not `Object`. – Drunya Jan 25 '20 at 17:39
2

In essence, you just break nested if/else condition checking into several methods. Why not change both the consumer and the supplier.

public <T> void ifChangedT(String key, Consumer<T> consumer, Supplier<T> supp) {
    ...
    consumer.accept(supp.get());
}

It's an example of Premature optimization in my opinion. Sometimes by leaving the nested if/else it is, you can get a simple and clear code style, although coupled.

Iceberg
  • 2,744
  • 19
  • 19
  • Of course :) It's so simple when seen, but hard to find when you're already down the wrong path. You may increase upvotes if you package it in a small compilable & runnable proof of concept. – Scratte Jan 25 '20 at 18:48
  • good thought, just that it lacked the usage of `key` as in the original question and could have made [use of a `Function`](https://stackoverflow.com/a/59914201/1746118) instead of that as well. – Naman Jan 26 '20 at 02:45
0

Given the current code in question and close to what is mentioned in sully's answer, you can make use of a Function defined along with the generic Consumer to get the value to consume:

public static <T> void ifChangedGeneric(String key, Consumer<T> consumer, Function<String, T> function) {
    consumer.accept(function.apply(key));
}

The implementation could be further used as:

public static void main(String[] args) {
    ifChangedGeneric("key", <Class>::useString, <Class>::getString);
    ifChangedGeneric("true", <Class>::useBoolean, <Class>::getBoolean);
}

With a sample implementation of the getBoolean/String and useBoolean/String methods as follows...

static Boolean getBoolean(String key) {
    return key.equalsIgnoreCase("true") ? Boolean.TRUE : Boolean.FALSE;
}

static void useBoolean(Boolean bool) {
    System.out.println("Boolean implementation!");
    System.out.println(bool.equals(Boolean.TRUE));
}

static String getString(String key) {
    return key + ": naman";
}

static void useString(String str) {
    System.out.println("String implementation!");
    System.out.println(str);
}

The output generated would be:

String implementation!
key: naman
Boolean implementation!
true
Naman
  • 27,789
  • 26
  • 218
  • 353