方法是一个有参数,有名字并且和对象关联的代码块,对象(更确切叫法是消息的接收者)调用方法,返回方法中最后一个表达式(ruby中基本上没有语句的概念,全是表达式)的值。很多语言都区分方法和函数,方法和对象相关。在ruby中,一切都是对象,即使你定义一个全局的函数,看上去不和任何对象关联,而实际上它被严格的定义为Object类的私有方法
irb(main):012:0> def hello
irb(main):013:1> end
=> nil
irb(main):014:0> Object.private_methods.grep :hello
=> [:hello]
为了方便,方法的名字以小写字母开头,当然也可以用大写字母开头,但是这样会和一般的常量混,当方法名超过一个单词时,可以用下划线将它们分开。ruby的方法名中可以有各式各样的符号,+,-,×等等,你可以为任何你想到的操作符定义成方法,唯一例外的是负号和正号,得叫'+@,-@'。
方法的参数:
加不加括号?加空隔不加括号,加括号不加空隔,强调是方法调用的时候加上括号,其它时候只要不出现语法问题,在明确的情况下,我想这是自由滴。
方法的参数在方法的名字之后,ruby的方法参数有很多种形式,ruby1.8与1.9又有一些微小的差异。ruby方法参数形式主要有:一般的,有默认值的,带*号的,hash,和带&的。一般的不用说了,首当其冲最好是放在参数列表的最前面。
当你定义一个方法的时候,你可以为一些参数指定默值。
def prefix(s, len=1)
s[0,len]
end
prefix("Ruby", 3) # => "Rub"
prefix("Ruby") # => "R"
#很明显参数不仅仅只是常量,可以是实例变量,也可以是有关前一参数的表达式
def suffix(s, index=s.size-1)
s[index, s.size-index]
end
在ruby1.8里面,有默认值的参数只能出现在普通参数的后面,1.9放宽了这个限制,但是有默认值的参数还是必须要连在一起的,这很好理解。
irb(main):001:0> def hello(a,b,c='world',d)
irb(main):002:1> puts a,b,c,d
irb(main):003:1> end
=> nil
irb(main):004:0> hello 1,2,3
1
2
world
3
=> nil
irb(main):005:0> hello 1,2,3,4
1
2
3
4
=> nil
#不允许的情况
irb(main):006:0> def hello(a,b,c='world',d,e='unpass')
irb(main):007:1> puts a,b,c,d,e
irb(main):008:1> end
SyntaxError: (irb):6: syntax error, unexpected '=', expecting ')'
def hello(a,b,c='world',d,e='unpass')
^
(irb):6: syntax error, unexpected ')', expecting $end
from /usr/local/bin/irb:12:in `<main>'
带*号的参数
有时候我们可能想要写一个可以传递任意个参数的方法,可以使用这种参数
def max(first, *rest)
max = first
rest.each {|x| max = x if x > max }
max
end
max(1) # first=1, rest=[]
max(1,2) # first=1, rest=[2]
max(1,2,3) # first=1, rest=[2,3]
在一个方法的参数里,不管是形参(parameter)还是实参(argument)这种参数只能有一个,在ruby1.8里,这种参数必须出现在所有的一般参数和有默认值的参数之后,但是在1.9里面,它的后面可能出现一般参数。
irb(main):001:0> def max(first,*rest,addtion)
irb(main):002:1> max=first
irb(main):003:1> puts addtion
irb(main):004:1> rest.each{|x|max=x if x>max}
irb(main):005:1> max
irb(main):006:1> end
=> nil
irb(main):007:0> max(1,2,3)
3
=> 2
irb(main):008:0> max(1,2,3,4)
4
=> 3
irb(main):009:0> max(1,2,3,4,5)
5
=> 4
#后面的一般参数分别是倒数的第一个,第二个,以此类推。
上面看到的是带*的参数为形参时*的作用,当参数是实参时,这种作用是逆向的,有点像并行赋值时*号的作用(但是他们是有区别的)
data = [3, 2, 1]
m = max(*data) # first = 3, rest=[2,1] => 3
#Consider what happens without the *:
m = max(data) # first = [3,2,1], rest=[] => [3,2,1]
#In Ruby 1.9, enumerators are splattable objects. To find the largest #letter in a string, for example, we could write:
max(*"hello world".each_char) # => 'w'
hash形式的参数的优点是不用记住参数的顺序,当然你可以传递一个对象,相杂整就杂整
def sequence(args)
n = args[:n] || 0
m = args[:m] || 1
c = args[:c] || 0
a = [] # Start with an empty array
n.times {|i| a << m*i+c } # Calculate the value of each array element
a # Return the array
end
#You might invoke this method with a hash literal argument like this:
sequence({:n=>3, :m=>5}) # => [0, 5, 10]
#用裸hash
sequence(:m=>3, :n=>5) # => [0, 3, 6, 9, 12]
# Ruby 1.9 的新语法,json形式,ruby语法越来越像命令了~
sequence c:1, m:3, n:5 # => [1, 4, 7, 10, 13]
#在省去参数的小括号,hash的大括号也要省去,要不然程序会把它看成一个#block
sequence {:m=>3, :n=>5} # Syntax error!
参数列表中带有&:
这种参数该是放在参数列表最后面的一种参数,&的作用有点像*,在形参里把一个block=>proc,方法调用时,逆向功能。
值得一提的是在方法内部,使用 yeild调用代码块是不需要显示的在参数列表中显示的
irb(main):020:0> def test
irb(main):021:1> yield
irb(main):022:1> end
=> nil
irb(main):023:0> test {puts "hello"}
hello
=> nil
在你显示的用&block声明后,你还是可以通过yield来调用代码块
irb(main):029:0> def test(&block)
irb(main):030:1> block.call()
irb(main):031:1> yield
irb(main):032:1> end
=> nil
irb(main):033:0> test{puts 'hello'}
hello
hello
=> nil
调用一个方法时,&的作用
a, b = [1,2,3], [4,5] # Start with some data.
summation = Proc.new {|total,x| total+x } # A Proc object for summations.
sum = a.inject(0, &summation) # => 6
sum = b.inject(sum, &summation) # => 15
#这样就把方法的实现抽象出来了~
在ruby1.9里面,Symbol类定义了一个to_proc方法,所以我们也可以用以下的这种形式来调用代码
words = ['and', 'but', 'car'] # An array of words
uppercase = words.map &:upcase # Convert to uppercase with String.upcase
upper = words.map {|w| w.upcase } # This is the equivalent code with a block
Symbol#to_pro
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
小结:总的来说,对于形参,参数的顺序是:一般的=》缺省的=》hash=》带*号的=》&block 不过不太会出现一起用到这些参数的情况。对于方法的近亲,block,lambda,proc的参数赋值和方法参数赋值是不太一样的,留到下次吧。
分享到:
相关推荐
hold the state of each method (java method, not a native method) invocations for the thread such as the local variables, method arguments, return values, intermediate results. Each entry in the Java ...
8. **去除方法参数提示**:在Preferences->Editor->Content Assist中取消Fill method arguments和Show guessed arguments的勾选,减少不必要的自动补全干扰。 9. **快捷键设置**:通过Preferences->General->Keys,...
**Native Method Arguments:** 本地方法可以接受各种类型的参数,包括基本数据类型、对象引用等。JNI提供了一套规则用于转换这些参数。 通过上述介绍,我们了解到JNI不仅仅是一个简单的接口,它还涉及到了许多细节...
7. **Using Blocks as Function/Method Arguments**: Blocks可以作为函数或方法的参数传递,这使得你可以在不同的上下文中重用相同的代码块,而无需重复编写相同的功能。 8. **Copying Blocks**: 复制block是在多个...
8. **可变参数长度的方法(Variable-Length Method Arguments)**:通过varargs关键字,可以创建接受可变数量参数的方法,提高了代码的灵活性。 9. **并发工具类(Concurrency Utilities)**:Java SE 5.0引入了...
六、可变参数长度的方法(Variable-Length Method Arguments) JDK5允许在方法签名中使用`...`来表示可变参数,比如`public void print(String... args)`。这种方式允许传入任意数量的字符串,提高了方法的灵活性。...
7. **方法的参数(method arguments)** - 参数列表应清晰,每个参数都有其特定的含义。 - 避免过多的参数,如果需要传递大量数据,考虑使用数组或对象。 8. **关键字:abstract, final, static** - `abstract`...
7. **可变参数长度的方法(Variable-Length Method Arguments)** 除了变量注入,JDK 1.5还支持在方法签名中使用可变参数长度,允许方法接收不定数量的参数。 8. **静态导入(Static Import)** 静态导入允许将类...
- **Method Arguments**:方法参数可以代表请求的各种组成部分,如路径变量、查询参数等。 - **Return Values**:方法的返回值可以是模型数据、视图名称或者直接的响应对象。 - **RequestParam**:用于获取...
Could not find method clean() for arguments [{type=class org.gradle.api.tasks.Delete}, build_458py9op120bi768cfxm5xc2wrunclosure1_run_closure1runclosure1_closure4@7daf132f] on object of type org....
Node.js API离线手册,2013年发行v0.8.22版本。...Where appropriate, property types, method arguments, and the arguments provided to event handlers are detailed in a list underneath the topic heading.
* @param args incoming main method arguments * @throws Exception on error */ void run(String... args) throws Exception; } ``` 使用 CommandLineRunner 我们可以编写一个简单的示例代码: ```java ...
3. **主方法参数(main method arguments)**:`String[] args`参数表示命令行参数。用户可以通过命令行传递这些参数给程序,程序可以解析这些参数来改变其行为。 4. **程序代码**:`main`方法内的代码块是程序实际...
方法参数实验室目标定义一个接受参数并在方法主体中使用该参数的方法。 定义一个接受两个参数并在方法主体中使用两个参数的方法。指示您将在lib/introduction.rb对方法进行编码。#introduction方法我们将使用测试...
AngularJS是Google维护的一款强大的前端JavaScript框架,用于构建交互式、单页面Web应用程序。这个压缩包文件"angular 1.3.0 rc3"包含了AngularJS的1.3.0 release candidate 3版本,这是一个重要的里程碑,因为它在...
`copyMethod`函数用于将`util`对象上的方法复制到`Collection`构造函数的原型上。这里的关键在于`apply`的使用,通过`[].slice.call(arguments)`将`arguments`对象转换为真正的数组,然后将`target`(即`this.data`...
然而,报错信息"The method `setAttribute(String, Object)` in the type `ServletRequest` is not applicable for the arguments `(String, int)"`表明在尝试调用`setAttribute`方法时,参数类型不匹配。...
方法参数实验室 目标 定义一个接受参数并在方法主体中使用该参数的方法。 定义一个接受两个参数并在方法主体中使用两个参数的方法。 指示 您将在lib/introduction.rb对方法进行编码。 #introduction方法 ...