I am playing with Java utility functions. I have the following code:
public class Checker<T>{
private T value;
private Function<T, T> callback;
private Checker(T value) {
this.value = value;
}
public static Checker when(String o) {
return new Checker<String>(o);
}
public static Checker when(int o) {
return new Checker<Integer>(o);
}
public Checker then(Function<T, T> callback) {
this.callback = callback;
return this;
}
public void execute() {
if (this.value instanceof String) {
this.callback.apply("123");
}
if (this.value instanceof Integer) {
this.callback.apply(123);
}
}
Checker.when("123").then(str -> {
return "";
}).execute();
Checker.when(123).then(str -> {
return "";
}).execute();
Now here I am getting an error for this.callback.apply("123")
as it requires T
and cannot cast it to String
.
Is it possible to have generic return types for Function<T,T>
? I can send T
, but then its received as an Object
in my lambda, but I want as String
or Integer
.
I made some changes in your Checker
class which make sense to me. I eliminated all the raw types, and I used the value
member in execute
. I added a return type of execute
, in order to be able to print its result.
class Checker<T>{
private T value;
private Function<T, T> callback;
private Checker(T value) {
this.value = value;
}
public static Checker<String> when(String o) {
return new Checker<>(o);
}
public static Checker<Integer> when(int o) {
return new Checker<>(o);
}
public Checker<T> then(Function<T, T> callback) {
this.callback = callback;
return this;
}
public T execute() {
return this.callback.apply(value);
}
public static void main (String[] args) {
Checker.when("123").then(str -> {
return "." + str + ".";
}).execute();
Checker.when(123).then(i -> {
return i + 100;
}).execute();
}
}
Now when you check your class with:
System.out.println (Checker.when("123").then(str -> "." + str + ".").execute());
System.out.println (Checker.when(123).then(i -> i + 100).execute());
You get:
.123.
223
This code can be even further simplified, like this:
static class Checker<T> {
private final T value;
private UnaryOperator<T> callback;
private Checker(T value) {
this.value = value;
}
public static <T> Checker<T> when(T o) {
return new Checker<>(o);
}
public Checker<T> then(UnaryOperator<T> callback) {
this.callback = callback;
return this;
}
public T execute() {
return this.callback.apply(value);
}
}
As the others suggested the code can be simplified, but why not make the calls chainable and also the class final, that way you'd have a simple and clean model:
final class Checker<T> {
private final T value;
private final UnaryOperator<T> callback;
private Checker(T value, UnaryOperator<T> callback) {
this.value = value;
this.callback = callback;
}
public static <T> Checker<T> when(T t) {
return new Checker<>(t, UnaryOperator.identity());
}
public Checker<T> then(UnaryOperator<T> callback) {
return new Checker<>(value, t -> callback.apply(this.callback.apply(t)));
}
public T execute() {
return callback.apply(value);
}
}
Rather than returning this
in the then()
this approach returns a completly new Checker-instance
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With