What's the nearest substitute for a function p

2018-12-31 17:07发布

I have a method that's about ten lines of code. I want to create more methods that do exactly the same thing, except for a small calculation that's going to change one line of code. This is a perfect application for passing in a function pointer to replace that one line, but Java doesn't have function pointers. What's my best alternative?

21条回答
若你有天会懂
2楼-- · 2018-12-31 17:31

Sounds like a strategy pattern to me. Check out fluffycat.com Java patterns.

查看更多
还给你的自由
3楼-- · 2018-12-31 17:32

If anyone is struggling to pass a function that takes one set of parameters to define its behavior but another set of parameters on which to execute, like Scheme's:

(define (function scalar1 scalar2)
  (lambda (x) (* x scalar1 scalar2)))

see Pass Function with Parameter-Defined Behavior in Java

查看更多
不再属于我。
4楼-- · 2018-12-31 17:34

@sblundy's answer is great, but anonymous inner classes have two small flaws, the primary being that they tend not to be reusable and the secondary is a bulky syntax.

The nice thing is that his pattern expands into full classes without any change in the main class (the one performing the calculations).

When you instantiate a new class you can pass parameters into that class which can act as constants in your equation--so if one of your inner classes look like this:

f(x,y)=x*y

but sometimes you need one that is:

f(x,y)=x*y*2

and maybe a third that is:

f(x,y)=x*y/2

rather than making two anonymous inner classes or adding a "passthrough" parameter, you can make a single ACTUAL class that you instantiate as:

InnerFunc f=new InnerFunc(1.0);// for the first
calculateUsing(f);
f=new InnerFunc(2.0);// for the second
calculateUsing(f);
f=new InnerFunc(0.5);// for the third
calculateUsing(f);

It would simply store the constant in the class and use it in the method specified in the interface.

In fact, if KNOW that your function won't be stored/reused, you could do this:

InnerFunc f=new InnerFunc(1.0);// for the first
calculateUsing(f);
f.setConstant(2.0);
calculateUsing(f);
f.setConstant(0.5);
calculateUsing(f);

But immutable classes are safer--I can't come up with a justification to make a class like this mutable.

I really only post this because I cringe whenever I hear anonymous inner class--I've seen a lot of redundant code that was "Required" because the first thing the programmer did was go anonymous when he should have used an actual class and never rethought his decision.

查看更多
看淡一切
5楼-- · 2018-12-31 17:36

oK, this thread is already old enough, so very probably my answer is not helpful for the question. But since this thread helped me to find my solution, I'll put it out here anyway.

I needed to use a variable static method with known input and known output (both double). So then, knowing the method package and name, I could work as follows:

java.lang.reflect.Method Function = Class.forName(String classPath).getMethod(String method, Class[] params);

for a function that accepts one double as a parameter.

So, in my concrete situation I initialized it with

java.lang.reflect.Method Function = Class.forName("be.qan.NN.ActivationFunctions").getMethod("sigmoid", double.class);

and invoked it later in a more complex situation with

return (java.lang.Double)this.Function.invoke(null, args);

java.lang.Object[] args = new java.lang.Object[] {activity};
someOtherFunction() + 234 + (java.lang.Double)Function.invoke(null, args);

where activity is an arbitrary double value. I am thinking of maybe doing this a bit more abstract and generalizing it, as SoftwareMonkey has done, but currently I am happy enough with the way it is. Three lines of code, no classes and interfaces necessary, that's not too bad.

查看更多
浪荡孟婆
6楼-- · 2018-12-31 17:36

To do the same thing without interfaces for an array of functions:

class NameFuncPair
{
    public String name;                // name each func
    void   f(String x) {}              // stub gets overridden
    public NameFuncPair(String myName) { this.name = myName; }
}

public class ArrayOfFunctions
{
    public static void main(String[] args)
    {
        final A a = new A();
        final B b = new B();

        NameFuncPair[] fArray = new NameFuncPair[]
        {
            new NameFuncPair("A") { @Override void f(String x) { a.g(x); } },
            new NameFuncPair("B") { @Override void f(String x) { b.h(x); } },
        };

        // Go through the whole func list and run the func named "B"
        for (NameFuncPair fInstance : fArray)
        {
            if (fInstance.name.equals("B"))
            {
                fInstance.f(fInstance.name + "(some args)");
            }
        }
    }
}

class A { void g(String args) { System.out.println(args); } }
class B { void h(String args) { System.out.println(args); } }
查看更多
情到深处是孤独
7楼-- · 2018-12-31 17:37

Wow, why not just create a Delegate class which is not all that hard given that I already did for java and use it to pass in parameter where T is return type. I am sorry but as a C++/C# programmer in general just learning java, I need function pointers because they are very handy. If you are familiar with any class which deals with Method Information you can do it. In java libraries that would be java.lang.reflect.method.

If you always use an interface, you always have to implement it. In eventhandling there really isn't a better way around registering/unregistering from the list of handlers but for delegates where you need to pass in functions and not the value type, making a delegate class to handle it for outclasses an interface.

查看更多
登录 后发表回答