I don't want to have a normal lambda implementing a method and redefine it's toString as a added value. I want the lambda expression implement only the toString method. I know I am not expressing it very well but I am sure you will understand me with this example.
public class LambdaToStringTest {
public interface ToStringInterface {
public abstract String toString();
}
public static void main(String[] args) {
print("TRACE: %s", (ToStringInterface)()->someComputation()); // <<-- ERROR: The target type of this expression must be a functional interface
}
private static void print(String format, Object... args) {
System.out.println(String.format(format, args));
}
}
It compiles if I change the name of the method but then it does not override toString so print method will not print what is expected.
This is an attempt to define a log subsystem that evaluates lambdas only when needed (when it is really going to be printed) but being compatible with non-lambda arguments. I know other ways to achieve it but I wonder why I can't do it this way and if there is a workaround or I am doing something wrong,
As fge points out, interfaces cannot declare methods from the Object class (toString, equals, hashCode).
I think Holger is correct in pointing you to Supplier, and I think given your stated purpose of creating a lazy log evaluator, you should just hand the casting inside your print method. To help with the syntax of your print calls, you can create a utility method that essentially performs the cast for you:
OUTPUT
Functionals need to know their type pretty quickly, which means you'll have a ton of casts to ToStringInterface if you try to stay too close to your original idea. Instead of the cast, you can call a static method.
Honestly though, Holger's comment is what I would do -
Short answer, you can't.
@FunctionalInterface
s cannot be used to "override" methods fromObject
.You can implement
Formattable
however, with a virtual extension method. Note: code below is UNTESTED:I propose this solution since you are using
String.format()
which makes use of this interface.Or you can just define your own interface. Or even write a wrapper for this interface which calls
.toString()
in.asString()
. Choices are many.