directory search
Ruby用户指南 3、开始 4、简单的例子 5、字符串 6、正则表达式 7、数组 8、回到那些简单的例子 9、流程控制 10、迭代器 11、面向对象思维 12、方法 13、类 14、继承 15、重载方法 16、访问控制 17、单态方法 18、模块 19、过程对象 20、变量 21、全局变量 22、实变量 23、局部变量 24、类常量 25、异常处理:rescue 26、异常处理:ensure 27、存取器 28、对象的初始化 29、杂项 RGSS入门教程 1、什么是RGSS 2、开始:最简单的脚本 3、数据类型:数字 4、数据类型:常量与变量 5、数据类型:字符串 6、控制语句:条件分歧语句 7、控制语句:循环 8、函数 9、对象与类 10、显示图片 11、数组 12、哈希表(关联数组) 13、类 14、数据库 15、游戏对象 16、精灵的管理 17、窗口的管理 18、活动指令 19、场景类 Programming Ruby的翻译 Programming Ruby: The Pragmatic Programmer's Guide 前言 Roadmap Ruby.new 类,对象和变量 容器Containers,块Blocks和迭代Iterators 标准类型 深入方法 表达式Expressions 异常,捕捉和抛出(已经开始,by jellen) 模块 基本输入输出 线程和进程 当遭遇挫折 Ruby和它的世界 Ruby和Web开发 Ruby Tk Ruby 和微软的 Windows 扩展Ruby Ruby语言 (by jellen) 类和对象 (by jellen) Ruby安全 反射Reflection 内建类和方法 标准库 OO设计 网络和Web库 Windows支持 内嵌文档 交互式Ruby Shell 支持 Ruby参考手册 Ruby首页 卷首语 Ruby的启动 环境变量 对象 执行 结束时的相关处理 线程 安全模型 正则表达式 字句构造 程序 变量和常数 字面值 操作符表达式 控制结构 方法调用 类/方法的定义 内部函数 内部变量 内部常数 内部类/模块/异常类 附加库 Ruby变更记录 ruby 1.6 特性 ruby 1.7 特性 Ruby术语集 Ruby的运行平台 pack模板字符串 sprintf格式 Marshal格式 Ruby FAQ Ruby的陷阱
characters

方法调用

  • super
  • 带块的方法调用
  • yield

例:

foo.bar()
foo.bar
bar()
print "hello world\n"
print
Class::new

语法:

[表达式  `.'] 标识符 [`(' 表达式 ... [`*' [表达式]],[`&' 表达式] `)']
[表达式 `::'] 标识符 [`(' 表达式 ... [`*' [表达式]],[`&' 表达式] `)']

方法调用表达式表示调用被调(receiver,"."左侧表达式的值)的方法。若未指定被调,则调用self的方法。

"."与"::"的意义大体相同。但表示常数时,必须使用"::"(例:Math::PIErrno::ERANGE)。若写成

Klass::Foo

的话,通常会被认为是常数。请注意,通常是将"::"用作类方法的调用。若方法名是以大写字母开始的时候,要写成

Klass.Foo

或者写成

Klass::Foo()

但要用括号显式地表明这是方法调用。

方法名中除了通常的标识符以外,还可以添加"?"或"!"等后缀。通常在布尔型(返回真或伪的方法)方法名后添加"?",在比同名(无"!")方法更具破坏性的方法名(例:tr和tr!)后添加"!"。

若最后一个参数带"*"的话,将会先展开该参数的值,然后才传递。也就是:

foo(1,*[2,3,4])
foo(1,*[])

和下例

foo(1,2,3,4)
foo(1)

等效。

若最后一个参数带"&",则该参数指定的过程对象(Proc)以及方法对象(Method)等会被当作一个块传递给方法。详情请参考迭代器

方法调用时,private方法只能用函数形式(省略被调的形式)来调用。而protected方法只能在拥有该方法的对象的方法定义表达式内进行调用。(请参考方法调用的限制)

super

例:

super
super(1,2,3)

语法:

super
super(表达式, ... )

super将调用被当前方法覆盖的父类中的同名方法。若省略括号和参数时,将会把当前方法的参数原封不动地传递给父类中的同名方法。若调用时不想使用参数的话,请使用括号显式地标出,像super()这样。

例:

class Foo
  def foo(arg=nil)
    p arg
  end
end

class Bar < Foo
  def foo(arg)
    super(5)       # 以5作为参数进行调用
    super(arg)     # 以5作为参数进行调用
    super          # 以5作为参数进行调用,super(arg)的简写
    arg = 1
    super          # 以1作为参数进行调用,super(arg)的简写
    super()        # 无参数的调用
  end
end
Bar.new.foo 5

带块的方法调用

例:

[1,2,3].each do |i| print i*2, "\n" end
[1,2,3].each {|i| print i*2, "\n" }

语法:

method(arg1, arg2, ...)  do [`|' 表达式 ... `|'] 表达式 ... end
method(arg1, arg2, ...) `{' [`|' 表达式 ... `|'] 表达式 ... `}'
method(arg1, arg2, ..., `&' proc_object)

所谓带块的方法是指,为了对控制结构进行抽象化而设计的方法。最初常用于对循环进行抽象化,所以有时也叫迭代器。将do...end或{...}中的代码片段(也就是块)添加在方法后面,然后再调用该方法时,就能从该方法内部对快进行计算。在带块的方法内进行块调用时使用 yield 表达式。传给yield的值会被赋值给夹在"||"中的变量。

{...}比do...end块的结合能力强。例如:

foobar a, b do .. end   # foobar 是带块的方法
foobar a, b { .. }      # b    成了带块的方法

块中首次被赋值(声明)的局部变量的作用域仅限于该块。例如:

foobar {
  i = 20                # 声明了局部变量i
   ...
}
print defined? i        # 此处的i尚未定义,false
foobar a, b do
  i = 11                # 声明了一个新变量i
   ...
end

如下所示,在块外仍然有效。

i = 10
[1,2,3].each do |m|
  p i * m               # 马上就能使用i
end

还可以把过程对象( Proc )当作块传递给带块的方法。这时要在过程对象名前面添加"&",并把该过程对象传递给带块的方法的最后一个参数。除了过程对象以外,还可以传递方法对象( Method )。这时将生成一个调用该方法的过程对象,然后把这个过程对象传给带块的方法。

pobj = proc {|v|
  p v
}

[1,2,3].each(&pobj)
=> 1
   2
   3

ruby 1.7 特性: 在version 1.7中,若该对象自带to_proc方法的话,就可以把它当作带"&"的参数传给带块方法(默认状态下,Proc、Method对象都有to_proc方法)。方法调用时会执行to_proc,它将返回Proc对象。

class Foo
  def to_proc
    Proc.new {|v| p v}
  end
end

[1,2,3].each(&Foo.new)

=> 1
   2
   3

带块方法的返回值与通常的方法是一样的。若块中的 break 引起中断时,将返回nil。 ruby 1.7 特性 :若break带参数的话,该参数的值就是带块方法的返回值。

yield

例:

yield data

语法:

yield `(' [表达式 [`,' 表达式 ... ]] `)'
yield [表达式 [`,' 表达式 ... ]]

把参数传给块之后,对块进行计算。因为yield定义迭代器,所以是在方法定义内使用。

def foo
  yield(1,2)
end

foo {|a,b| p [a,b]}

对块参数进行赋值时遵从多重赋值规律。若执行yield时,方法并没有带块(不是迭代器)的话,就会引发 LocalJumpError 异常。

yield将会返回块内最后被计算的表达式的值。若因 next 引起块的运行中断的话,返回nil。

ruby 1.7 特性 :若next带参数的话,该参数的值就是yield的返回值。

ruby 1.8 特性 :关于块参数的交付问题,以后可能会对下述内容进行变更(会发出警告)。

def foo
  yield 1,2,3
end

foo {|v| p v}

# => -:5: warning: multiple values for a block parameter (3 for 1)
     [1, 2, 3]

应该写成

yield [1,2,3]

或者

foo {|*v| p v}

这样才对。虽然现在使用

v = 1,2,3

这样的多重赋值还不会有警告,但最好不要使用。


Previous article: Next article: