Programming Ruby(读书笔记)-8章(方法详解)

8.1 方法定义

def methodName(首字母小写/下划线)。若使用了大写,在调用的时候,ruby会认为这个一个常量,而不是一个方法,就会出现错误。

方法后可以跟? ! =。如果方法返回是boolean,则代?

1.even? #=>false
2.even? #=>true
1.instance_of(Fixnum) #=>true

 如果方法会修改接收者(object.method,那object就是这个方法的接受者),或者方法的操作有危险性,使用!。比如String有chop与chop!,前者返回一个修改COPY,后者直接修改当前string。

如果以=结尾(suffix)用以表示给=左边赋值。

入参

入参可设默认值,使用arg=expression,当调用者没有显示的设时使用该默认值,expression可以引用前面的入参。

 

#示例演示第二个参数引用第一个参数
#string * 整数,表示string复制整数个。
def surround(word, pad_width=word.length/2)
  "[" * pad_width + word + "]" * pad_width
end
surround("elephant") #=>"[[[[elephant]]]]"
surround("fox") # => "[fox]"
surround("fox", 10) # => "[[[[[[[[[[fox]]]]]]]]]]
 返回值

 

ruby返回方法第后一行的执行结果,或者显示的return。

 

变长的参数列表

变化参数使用*作前缀。不要求放在最后一个位置。变长参数只允许有一个。

#分配给变长参数的是一个数组
def varargs(arg1, *rest)
  "arg1=#{arg1}".   rest=#{rest.inspect}"
end
varargs("one") # => arg1=one. rest=[]
varargs("one", "two") # => arg1=one. rest=["two"]
varargs "one", "two", "three" # => arg1=one. rest=["two", "three"]

 变长参数常用来表示参数可输可不输。在调用父方法时,对这种参数的传递需要注意。

#调用父方法传变长参数,使用super就可以,表示有就传,没有就不传
class Child < Parent
  def do_something(*not_used)
    #our processing
    super
  end
end
#对于这种情况,*not_used直接使用*就可以了。

 变长参数可放在任意参数的位置:

def split_apart(first, *splat, last)
  puts "First: #{first.inspect}, splat: #{splat.inspect}, " +
         "last: #{last.inspect}"
end
split_apart(1,2)
split_apart(1,2,3)
split_apart(1,2,3,4)
produces:
First: 1, splat: [], last: 2
First: 1, splat: [2], last: 3
First: 1, splat: [2, 3], last: 4

 上面还可以直接写成:

#直接使用*
def split_apart(first, *, last)

 变长参数:不允许多个,不可以使用默认值。

 

方法,块

方法内使用yield(args)调用传入的块。

如果最后一个参数使用&(ampersand)标注,则表示这个参数接收块,并会被转换为一个Proc对象,

class TaxCalculator
  def initialize(name, &block)
    @name, @block = name, block #这种赋值方式,有意思
  end
  def get_tax(amount)
    puts "#@name on #{amount} = #{ @block.call(amount)}" # call中amount入参
  end
end
tc = TaxCalculator.new("Sales tax") {|amt| amt * 0.075 }
tc.get_tax(100) # => "Sales tax on 100 = 7.5"
tc.get_tax(250) # => "Sales tax on 250 = 18.75"

 

8.2 Calling a Method(方法调用)

 调用一个方法,可指定也可以不指定接收者(object.method=object就是接收者)。

 

 

connection.download_mp3("jitterbug") {|p| show_process(p)}
#connection是接收者。
当方法被调用时,Ruby首先将self设给接收者,然后调用接收者的该方法。
如果方法是类方法或者模块方法,则接收者就是类名或模块名。

 

Passing Parameters to a Method

Method Return Values

每个方法都有返回值,

#这个示例倒可以看看case when else end 语法
def meth_two(arg)
  case
  when arg > 0 then "positive
  when arg < 0 then "negative
  else "zero"
  end
end
meth_two(23) # => "positive"
meth_two(0) # => "zero"

 Ruby的return可以是一外语句块。也常用于循环时跳出

#方法可以返回多个值
def meth_three
  100.times do |num|
    square = num*num
    return num, square if square > 1000
  end
end
meth_three # => [32, 1024]
#可以使用多个接收参数
num, square = meth_threee 

 

Splat!Expanding Collections in Methond Calls

#参数可以由集合或者可迭代对象转换而来
def five(a, b, c, d, e)
"I was passed #{a} #{b} #{c} #{d} #{e}"
end
five(1, 2, 3, 4, 5 ) # => "I was passed 1 2 3 4 5"
five(1, 2, 3, *['a', 'b']) # => "I was passed 1 2 3 a b"
five(*['a', 'b'], 1, 2, 3) # => "I was passed a b 1 2 3"
five(*(10..14)) # => "I was passed 10 11 12 13 14"
five(*[1,2], 3, *(4..5)) # => "I was passed 1 2 3 4 5"
注意,参数个数一定要对应的上,如果调用时多了或少了,都会抛出错误

 

Making Blocks More Dynamic

print "(t)imes or (p)lus"
operator = gets
print "number:"
number = Integer(gets)
if operator = ~ /^t/
  calc = lambda {|n| n*number}
else
  calc = lambda {|n| n+number}
puts((1..10).collect(&calc).join(", "))
produces:
(t)imes or (p)lus: t
number: 2
2, 4, 6, 8, 10, 12, 14, 16, 18, 20

#如果方法参数的最后一个使用&作为前缀,ruby认为它是一个Proc对象,会把它从参数列表中删除,并转为一个块代码供内部调用。
#这里不明白(1..10).collect方法的语

 

 Hash及关键字参数

#:titles表示希望返回的内容,第二个参数是参数hash
class SongList
  def search(field, params)
    # ...
  end
end
list = SongList.new
list.search(:titles, { genre: "jazz", duration_less_than: 270 })
有一个快捷的写法:

list.search(:titles, genre: "jazz", duration_less_than: 270)
ruby会自动把它们组装为一个hash传给方法。

 

Keyword Argument Lists

#下面这个方法需要判断入参的hash中是否有其它非法参数
def search(field, options)
  options = { duration: 120 }.merge(options)
  if options.has_key?(:duration)
    duration = options[:duration]
    options.delete(:duration)
  end
  if options.has_key?(:genre)
    genre = options[:genre]
    options.delete(:genre)
  end
  fail "Invalid options: #{options.keys.join(', ')}" unless options.empty?
#如果options不为空,则表示有非法的参数,就失败
# rest of method
end
#在Ruby 2中,可以在方法中定义关键字参数,然后Ruby会自动将值设给对应的参数。
并且会进行参数校验
--------------------这些是2.0的语法-----------------------

结束。

你可能感兴趣的:(programming)