mktany2k / funcito

Automatically exported from code.google.com/p/funcito
0 stars 0 forks source link

wrap static methods #31

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
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.

Original issue reported on code.google.com by kandpwel...@gmail.com on 7 Dec 2011 at 6:42

GoogleCodeExporter commented 9 years ago
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());

Original comment by kandpwel...@gmail.com on 11 Dec 2011 at 6:42

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
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...?

Original comment by kandpwel...@gmail.com on 12 Dec 2011 at 8:32

GoogleCodeExporter commented 9 years ago
splitting off the chained-calls idea (2nd post, Dec. 10) as a separate issue

Original comment by kandpwel...@gmail.com on 23 Jan 2012 at 8:25

GoogleCodeExporter commented 9 years ago
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.

Original comment by palotai....@gmail.com on 28 Jun 2012 at 1:28

GoogleCodeExporter commented 9 years ago
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...

Original comment by kandpwel...@gmail.com on 19 Jul 2012 at 8:26

GoogleCodeExporter commented 9 years ago
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.

Original comment by kandpwel...@gmail.com on 24 Aug 2012 at 3:52