目录搜索
Ruby用户指南3、开始4、简单的例子5、字符串6、正则表达式7、数组8、回到那些简单的例子9、流程控制10、迭代器11、面向对象思维12、方法13、类14、继承15、重载方法16、访问控制17、单态方法18、模块19、过程对象20、变量21、全局变量22、实变量23、局部变量24、类常量25、异常处理:rescue26、异常处理:ensure27、存取器28、对象的初始化29、杂项RGSS入门教程1、什么是RGSS2、开始:最简单的脚本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前言RoadmapRuby.new类,对象和变量容器Containers,块Blocks和迭代Iterators标准类型深入方法表达式Expressions异常,捕捉和抛出(已经开始,by jellen)模块基本输入输出线程和进程当遭遇挫折Ruby和它的世界Ruby和Web开发Ruby TkRuby 和微软的 Windows扩展RubyRuby语言 (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 FAQRuby的陷阱
文字

方法调用

  • 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

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


上一篇:下一篇: