Ruby入门

8 最美不过简简单单

2018-03-14  本文已影响1人  彩虹门票

正如我们在上一篇文章中看到的那样,循环和迭代允许我们一遍遍地重复做相同的事情。但在现实中有时我们想在程序中其他地方重复做同样的事情。比如说我们在写一个面向心理专业学生所做的调查问卷,而我这里已经有一份他们提供给我的调查问卷,类似下面这样:

puts 'Hello, and thank you for taking the time to'
puts 'help me with this experiment.  My experiment'
puts 'has to do with the way people feel about'
puts 'Mexican food.  Just think about Mexican food'
puts 'and try to answer every question honestly,'
puts 'with either a "yes" or a "no".  My experiment'
puts 'has nothing to do with bed-wetting.'
puts

# We ask these questions, but we ignore their answers.

goodAnswer = false
while (not goodAnswer)
  puts 'Do you like eating tacos?'
  answer = gets.chomp.downcase
  if (answer == 'yes' or answer == 'no')
    goodAnswer = true
  else
    puts 'Please answer "yes" or "no".'
  end
end

goodAnswer = false
while (not goodAnswer)
  puts 'Do you like eating burritos?'
  answer = gets.chomp.downcase
  if (answer == 'yes' or answer == 'no')
    goodAnswer = true
  else
    puts 'Please answer "yes" or "no".'
  end
end

# We pay attention to *this* answer, though.
goodAnswer = false
while (not goodAnswer)
  puts 'Do you wet the bed?'
  answer = gets.chomp.downcase
  if (answer == 'yes' or answer == 'no')
    goodAnswer = true
    if answer == 'yes'
      wetsBed = true
    else
      wetsBed = false
    end
  else
    puts 'Please answer "yes" or "no".'
  end
end

goodAnswer = false
while (not goodAnswer)
  puts 'Do you like eating chimichangas?'
  answer = gets.chomp.downcase
  if (answer == 'yes' or answer == 'no')
    goodAnswer = true
  else
    puts 'Please answer "yes" or "no".'
  end
end

puts 'Just a few more questions...'

goodAnswer = false
while (not goodAnswer)
  puts 'Do you like eating sopapillas?'
  answer = gets.chomp.downcase
  if (answer == 'yes' or answer == 'no')
    goodAnswer = true
  else
    puts 'Please answer "yes" or "no".'
  end
end

# Ask lots of other questions about Mexican food.

puts
puts 'DEBRIEFING:'
puts 'Thank you for taking the time to help with'
puts 'this experiment.  In fact, this experiment'
puts 'has nothing to do with Mexican food.  It is'
puts 'an experiment about bed-wetting.  The Mexican'
puts 'food was just there to catch you off guard'
puts 'in the hopes that you would answer more'
puts 'honestly.  Thanks again.'
puts
puts wetsBed


上面的程序有些太长,许多代码都是重复的(围绕着食物问题的代码是一样的,只有在尿床的部分有些许不同)。代码重复总是件不好的事,但我们又没法将它们写成一个大的循环或迭代中去,因为我们通常会在问题中间做点其他事情。鉴于这种情况我们就很有必要写一个方法,比如下面这种:

def sayMoo
  puts 'mooooooo...'
end

但运行后程序没有输出sayMoo。这是为什么?因为我们还没有告诉它去输出(我们只是告诉程序如何做,但还没指示程序去做)。让我们再来试验一下:

mooooooo...
mooooooo...
coin-coin
mooooooo...
mooooooo...

嗯,成功运行。(考虑到你们可能不太了解法语,在程序中有一个法国的鸭子,因为在法国鸭子的叫声就是coin-coin

在上面的程序中我们就成功定义(define)了sayMoo的方法(方法的名字类似变量命名方式,以小写字母开头,但也有少数以+或==开头的例外)。但是难道方法不是通常要与对象一起用的吗?好吧,的确需要这样用,但上面的例子有些类似pusgets,方法是以整个程序为对象的,在下个章节中我们将会看到如何将方法与其他对象一起用上,但是我们要首先学习…

方法中参数的使用

你可能已经注意到类似gets``to_s``reverse等方法可以直接向对象进行调用,但类似+``-``puts等需要参数才能告诉对象如何使用这种方法。比如你不能仅仅用5+,是吧?你只是在告诉对象5去执行加法,但没告诉它增加多少……

为了给sayMoo增加参数(比如叫声的数量),可以这样做:

def sayMoo numberOfMoos
  puts 'mooooooo...'*numberOfMoos
end

sayMoo 3
puts 'oink-oink'
sayMoo  # This should give an error because the parameter is missing.

运行结果是:

mooooooo...mooooooo...mooooooo...
oink-oink
#<ArgumentError: wrong number of arguments (0 for 1)>

numberOfMoos是一个指向参数的变量:如果我键入的是sayMoo 3,那么参数是3,变量numberOfMoos是指向3的。

正如你所看到的:上面的程序中参数就是必须要提供的,别忘了如果你不提供参数,sayMoo要用什么去乘以'mooooooo...' ?你笨笨的电脑是有点懵逼的。

如果我们把Ruby中的对象比作英语中的名词,把Ruby中的方法比作动词,那么你可以把参数对应于英语中的副词(好比sayMoo,参数是教我们如何sayMoo)或某些情况下类似直接宾语(好比puts中的参数就是应该输出的相应内容)。

局部变量

在下面的代码中有两个变量:


输出结果是:
44 doubled is 88
两个变量分别是numnumTime2,它们都在我们定义的方法doubleThis中。类似之前你看到的所有变量都称作局部变量,因为这些变量只能在方法内部使用,在外部使用的话就会提示错误:
def doubleThis num
  numTimes2 = num*2
  puts num.to_s+' doubled is '+numTimes2.to_s
end

doubleThis 44
puts numTimes2.to_s

输出就会提示有错误:

44 doubled is 88
def_double.rb:7:in `<main>': undefined local variable or method `numTimes2' for main:Object (NameError)

提示中的undefined local variable…事实上我们的确定义了numTime2变量,但它没有位于我们想使用的地方,而只位于我们定义的方法中。

这样看似有些不便,但实际上确是非常棒的。在保证你没法更改方法中相应变量的同时,也确保其他人也无法随意改动,这样就不会将程序中的方法搞坏掉:

输出为:

HAHA!  I ruined your variable!
You can't even touch my variable!

在上面程序中有两个名字均为var的变量:一个在方法littlePest中,另一个则在方法外面。当我们用命令littlePest var时候,仅仅是字符串的传递,都指向同一个字符串。littlePest方法中将局部变量var指向nil,但对方法外部的另一个同样的变量var无任何影响。

上一篇 下一篇

猜你喜欢

热点阅读