1 | 2 | 3 | 4

20 分钟体验 Ruby

现在,深入研究我们的新程序,请注意以井号 (#) 开头的行。在 Ruby 中,一行中井号后面的任何内容都是注释,会被解释器忽略。文件的第一行是一种特殊情况,在类似 Unix 的操作系统下,它会告诉 shell 如何运行该文件。其余的注释只是为了清晰起见。

我们的 say_hi 方法变得稍微复杂了一些

# Say hi to everybody
def say_hi
  if @names.nil?
    puts "..."
  elsif @names.respond_to?("each")
    # @names is a list of some kind, iterate!
    @names.each do |name|
      puts "Hello #{name}!"
    end
  else
    puts "Hello #{@names}!"
  end
end

它现在查看 @names 实例变量来做出决策。如果它是 nil,它只会打印三个点。不跟任何人打招呼,对吧?

循环和迭代—又名:迭代

如果 @names 对象响应 each,那么它就是你可以迭代的东西,所以迭代它并依次问候每个人。最后,如果 @names 是任何其他东西,只需让它自动转换为字符串并执行默认的问候。

让我们更深入地研究一下迭代器

@names.each do |name|
  puts "Hello #{name}!"
end

each 是一个接受代码块的方法,然后为列表中的每个元素运行该代码块,而 doend 之间的部分只是这样一个代码块。块类似于匿名函数或 lambda。管道字符之间的变量是此块的参数。

这里发生的事情是,对于列表中的每个条目,name 都绑定到该列表元素,然后使用该名称运行表达式 puts "Hello #{name}!"

大多数其他编程语言使用 for 循环来处理遍历列表,在 C 中看起来像这样

for (i=0; i<number_of_elements; i++)
{
  do_something_with(element[i]);
}

这可行,但不是很优雅。你需要一个像 i 这样的临时变量,必须找出列表的长度,并且必须解释如何遍历列表。Ruby 的方式要优雅得多,所有内务处理细节都隐藏在 each 方法中,你所需要做的就是告诉它如何处理每个元素。在内部,each 方法本质上会调用 yield "Albert",然后调用 yield "Brenda",然后调用 yield "Charles",以此类推。

块,Ruby 边缘上高度闪耀的光芒

当处理比列表更复杂的事物时,块的真正力量就体现出来了。除了在方法中处理简单的内务处理细节外,你还可以处理设置、拆卸和错误—所有这些都隐藏在用户的关注之外。

# Say bye to everybody
def say_bye
  if @names.nil?
    puts "..."
  elsif @names.respond_to?("join")
    # Join the list elements with commas
    puts "Goodbye #{@names.join(", ")}.  Come back soon!"
  else
    puts "Goodbye #{@names}.  Come back soon!"
  end
end

say_bye 方法不使用 each,而是检查 @names 是否响应 join 方法,如果响应,则使用它。否则,它只是将变量作为字符串打印出来。这种不关心变量实际类型的方法,仅依赖于它支持的方法被称为“鸭子类型”,正如“如果它走起来像鸭子,叫起来像鸭子...”那样。这样做的好处是,它不会不必要地限制支持的变量类型。如果有人提出一种新的列表类,只要它以与其他列表相同的语义实现 join 方法,一切都会按计划进行。

启动脚本

所以,这就是 MegaGreeter 类,文件的其余部分只是调用该类的方法。还有一个需要注意的最终技巧,那就是这行

if __FILE__ == $0

__FILE__ 是包含当前文件名称的魔术变量。$0 是用于启动程序的文件的名称。此检查表示“如果这是正在使用的主文件...” 这允许将文件用作库,而不是在该上下文中执行代码,但如果该文件用作可执行文件,则执行该代码。

考虑一下介绍

这就是 Ruby 快速浏览的全部内容。还有很多值得探索的地方,Ruby 提供的不同控制结构;块和 yield 的使用;作为 mixin 的模块;等等。我希望这种 Ruby 的味道能让你想了解更多。

如果是这样,请前往我们的文档区域,其中汇总了指向手册和教程的链接,所有这些都可以在线免费获得。