使用块相比普通方法有哪些好处?

4

我是一名Java程序员,正在学习Ruby...

但我不明白那些代码块能给我带来什么好处...比如将代码块作为参数传递的目的是什么?为什么不使用两个专门的方法来实现可重用性?

为什么有些代码在块中不能被重用?

我希望能够看到一些代码示例...

谢谢你的帮助!


除了下面的答案之外,需要注意的是,Ruby 中的块是闭包,可以轻松访问在相同作用域中定义的局部变量,无需显式地将它们传递给某个方法。 - Phrogz
2个回答

9
考虑一下在Java中您可能使用匿名类的一些事情。例如,它们通常用于插件行为,如事件监听器或为具有通用布局的方法参数化。
假设我们想编写一个方法,该方法接受列表并返回包含给定列表中满足特定条件的项目的新列表。在Java中,我们会编写一个接口:
interface Condition {
    boolean f(Object o);
}

然后我们可以写:

public List select(List list, Condition c) {
    List result = new ArrayList();
    for (Object item : list) {
        if (c.f(item)) {
            result.add(item);
        }
    }
    return result;
}

然后,如果我们想从列表中选择偶数,我们可以这样写:

List even = select(mylist, new Condition() {
    public boolean f(Object o) {
        return ((Integer) o) % 2 == 0;
    }
});

要用Ruby写出相同的代码,可以这样写:
def select(list)
  new_list = []
  # note: I'm avoid using 'each' so as to not illustrate blocks
  # using a method that needs a block
  for item in list
    # yield calls the block with the given parameters
    new_list << item if yield(item)
  end
  return new_list
end

然后,我们可以简单地选择偶数。
even = select(list) { |i| i % 2 == 0 }

当然,这个功能已经内置在Ruby中,所以在实践中你只需要这样做:
even = list.select { |i| i % 2 == 0 }

举个例子,考虑代码打开文件的情况。你可以这样写:

f = open(somefile)
# work with the file
f.close

但是,您需要考虑将close放在ensure块中,以防在处理文件时发生异常。您可以这样做:

open(somefile) do |f|
  # work with the file here
  # ruby will close it for us when the block terminates
end

嗯...谢谢,那是一个非常好的例子...我想我需要一些时间来适应这种思维方式。但这就是我试图学习Ruby的原因:D当你掌握它时,它是一个很好的解决方案。 - Cristiano Fontes
1
看一下Enumerable mixin - 里面有很多使用块的好方法的例子。我认为熟悉块是一个两部分的过程:1)开始理解一些使用块的标准方法;2)开始思考你自己编写的方法如何利用接受块。我还在上面的答案中添加了一个例子。 - mikej

2
块的概念是,它是高度本地化的代码,在调用站点上具有定义非常有用。您可以使用现有函数作为块参数。只需将其作为额外参数传递,并在前面加上 &。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接