什么是Java中的ruby块

时间:2019-11-29 11:55:37

标签: java ruby

Ruby块很方便用于将一些代码包装在调用方定义的某些块周围。

如何用Java做到这一点?

def myf(i)
  puts "start"
  yield i
  puts "end"
end

myf(3){ |i| puts i * 10 }
myf(4){ |i| puts i - 10 }

# outputs:
# start
# 30
# end
# start
# -6
# end

3 个答案:

答案 0 :(得分:4)

  

如何用Java做到这一点?

在Java中没有等效于Ruby块。 Ruby块在语法上是轻量级的,在语义上是轻量级的,它们不是对象。它们主要是语法结构,后面带有一些轻量级语义。在这种情况下,它们更像Java中增强的for循环。

您在Java中最接近的等效项是将functional interfacelambda expression组合在一起。使用java.util.function包中的预定义功能接口之一,即接口java.util.function.Consumer<T>,就是这样:

void myf(int i, java.util.function.Consumer<Integer> proc) {
    System.out.println("start");
    proc.accept(i);
    System.out.println("end");
}

您可以这样使用它:

myf(3, i -> System.out.println(i * 10));
myf(4, i -> System.out.println(i - 10));
// start
// 30
// end
// start
// -6
// end

但是,这等效于Ruby的块。这等效于Ruby的Proclambda literals,换句话说,它等效于此:

def myf(i, proc)
  puts "start"
  proc.(i)
  puts "end"
end

myf(3, -> i { puts i * 10 })
myf(4, -> i { puts i - 10 })

# start
# 30
# end
# start
# -6
# end

请注意,示例中的myf不使用块的结果,因此使用java.util.function.Function<T, R>对其进行建模将是不正确的。 Consumer<T>是用于“消耗”其参数但不返回任何内容的“函数”(实际上是一个过程)的正确接口,而Function<T, R>是用于“函数”的正确接口。需要一个参数并返回结果的函数。

答案 1 :(得分:3)

您的own answer是正确的,lambdas(与功能接口结合)使Java成为可能,但是它比使用java.util.function中的类型要简单得多。这是使用Function<T,R>的代码:

myf

public static int myf(int i, Function<Integer,Integer> fn) {
    System.out.println("start");
    int retval = fn.apply(i);
    System.out.println(retval);
    System.out.println("end");
    return retval;
}

使用它:

public static void main(String[] args) {
    myf(3, i -> i * 10);
//         ^^^^^^^^^^^−−−−−−−−−−−− lambda expression
    myf(4, i -> i - 10);
//         ^^^^^^^^^^^−−−−−−−−−−−− lambda expression
}

Live example

我使用Function是因为您的Java代码似乎表明您想要返回值。如果您不希望返回值,只需使用Consumer<T>

答案 2 :(得分:0)

在Java 1.8中,可以使用Lambda表达式获得所需的结果:

public class Temp {
    interface BlockBody {
        int op(int b);
    }

    public static int myf(int i, Temp.BlockBody blockBody) {
        System.out.println("start");
        int out = blockBody.op(i);
        System.out.println(out);
        System.out.println("end");
        return out;
    }


    public static void main(String[] args) {
        // block lambda function defined here
        Temp.BlockBody blockBody = (int a) -> {
            int c = a * 10;
            return c;
        };
        int result = Temp.myf(3, blockBody);

        // block body is changed
        Temp.BlockBody blockBody2 = (int a) -> {
            int c = a - 10;
            return c;
        };
        int result2 = Temp.myf(4, blockBody2);
    }
}

// outputs:
// start
// 30
// end
// start
// -6
// end