| Issue 31: | wrap static methods | |
| 2 people starred this issue and may be notified of changes. | Back to list |
I was using Funcito at work today, and I saw a few places where I was wishing I could have wrapped static methods. Example:
class MyClass{}
class Helper{
static public String doSomeTransform(MyClass sc) {
// do a lot of stuff that does not belong as a method on MyClass
}
}
I'm struggling with the semantics, but I wish I could do something like:
Function<SomeClass,String> f = functionFor( staticCallTo(Helper.class)
.doSomeTransform(any(MyClass.class)) );
As you can see, the method being wrapped may not exist in the same class which is essentially the argument of the function.apply().
As in all things, valuing your opinion.
Dec 12, 2011
Referring back to the OP:
I'm thinking thru static methods, and since statics are not a function of an instance-state, they should probably not be a function of the Method's class, in the same sense as a normal function. So maybe something more like the following for no-arg methods:
Function<Static<SomeClass>,String> f = functionFor(Funcito.staticCallTo(Helper.class)
.someStaticNoArgMethod() );
and like the following for 1-arg methods:
Function<Static<SomeClass>,String> f = functionFor(Funcito.staticCallTo(Helper.class)
.doSomeTransform(any(MyClass.class)) );
Or, on perhaps the 1-arg static call is actually a function of the argument:
Function<MyClass,String> f = functionFor(Funcito.staticCallTo(Helper.class)
.doSomeTransform(any(MyClass.class)) );
I don't know whether to give priority to the mathematical sense of "function", or to the object that owns the method, in defining the generic source type. In a sense it also gets more complicated, because even a static method can get static-state from the class, so the 1-arg static call could actually be seen as a function of 2 types: both the argument to the function and the static state of the method's class.
Most of the other pseudo-functional frameworks other than Guava do support the idea of Function2 (i.e., function of 2 inputs). I would want the API to be consistent in *how* it processed things, and just not support certain features in more limited (Guava) frameworks. So maybe I should not support static 1-arg methods in Guava, but OK in FJ, etc., as a function of 2 args there.
More thoughts...?
Jan 23, 2012
splitting off the chained-calls idea (2nd post, Dec. 10) as a separate issue
Jun 28, 2012
In a functional programming sense, I think the wrapped function should not have the enclosing static class in the signature (since the enclosing class is nothing just a module, or a package in Java).
So I would go for
Function<MyClass,String> f = functionFor(Funcito.staticCallTo(Helper.class)
.doSomeTransform(any(MyClass.class)) );
While in Java it is possible to override a static method in a subclass, I don't see this pattern used, and I think that is not without reason :)
As for chaining calls, at least in FJ, that it possible using the F abstraction (F#andThen(F)), so not really needed on the funcito level.
Jul 19, 2012
I've been giving this some thought -- since there is no such thing as "static polymorphism", I would probably have to do something like what they do in PowerMock: http://stackoverflow.com/q/5402507/433348 http://www.jayway.com/2009/05/17/mocking-static-methods-in-java-system-classes/ I'm not sure how well (or whether) that would work within Funcito. Something to explore...
Aug 24, 2012
Looking into Powermock led me into JMockit, which is using Java instrumentation API. This would force the use of an agent, which can be automatic in Java 6+, or force a command line option in Java 5, and also require some classpath ordering. I'm concerned that such a solution might affect runtime speed. Not sure if I could limit the scope of *when* method interception happened. If not, this may not be feasible. Same thing for wrapping constructors (see Issue 56). Good news is, that if this is do-able, it may open up the door to wrapping methods/chains that are final or final classes.
Labels:
-Type-Design Type-Enhancement
|
In addition I am wondering whether I could extend the capabilities of both static 1-arg methods and non-static no-arg methods, so that we could build chained calls as Functions? In my mind, I think it seems possible. Example of what it would look like: public class MyClass1 { public MyClass2 getMC2() {...} } public class MyClass2 { public String getStringVal() {...} } MyClass1 myClass1Stub = callsTo(MyClass1.class); Function<MyClass1,String> chained = functionFor(myClass1Stub.getMC2().getStringVal());