• 软件测试技术
  • 软件测试博客
  • 软件测试视频
  • 开源软件测试技术
  • 软件测试论坛
  • 软件测试沙龙
  • 软件测试资料下载
  • 软件测试杂志
  • 软件测试人才招聘
    暂时没有公告

字号: | 推荐给好友 上一篇 | 下一篇

ruby方法常见问题

发布: 2007-7-04 20:03 | 作者: admin | 来源:  网友评论 | 查看: 54次 | 进入软件测试论坛讨论

领测软件测试网 5.1 向对象发出消息之后,将按照什么顺序来搜索要执行的方法?

将依次搜索特殊方法、本类中定义的方法和超类(包括Mix-in进来的模块。写成 类名.ancestors。)中定义的方法,并执行所找到的第一个方法。若没有找到方法时,将按照同样的顺序来搜索method_missing。

module Indexed def [](n) to_a[n] end end class String include Indexed end p String.ancestors # [String, Indexed, Enumerable, Comparable,
Object, Kernel] p "abcde".gsub!(/./, "\\&\n")[1]

遗憾的是上述代码返回的是10,而并非预期的"b\n"。这是因为系统在String类中搜索[],在遇到Indexed中定义的方法之前就已经完成了匹配,所以如此。若直接在Class String中重定义[]的话,就会如您所愿了。

5.2 +和-是操作符吗?

+和-等是方法调用,而并非操作符。因此可进行overload(重定义)。

class MyString < String def +(other) print super(other) end end

但以下内容及其组合(!=、!~)则是控制结构,不能进行重定义。

=, .., ..., !, not, &&, and, |, or, ~, ::

重定义(或者定义)操作符时,应该使用形如+@或-@这样的方法名。

=是访问实例变量的方法,您可以在类定义中使用它来定义方法。另外,+或-等经过适当的定义之后,也可以进行形如+=这样的自赋值运算。

def attribute=(val) @attribute = val end 5.3 Ruby中有函数吗?

Ruby中看似函数的部分实际上都是些省略被调(self)的方法而已。例如

def writeln(str) print(str, "\n") end writeln("Hello, World!")

中看似函数的部分实际上是Object类中定义的方法,它会被发送到隐藏的被调self中。因此可以说Ruby是纯粹的面向对象语言。

对内部函数这种方法来说,不管self如何,它们总是返回相同的结果。因此没有必要计较被调的问题,可以将其看作函数。

5.4 可以在外部使用对象的实例变量吗?

不能直接使用。若想操作实例变量,必须事先在对象中定义操作实例变量的方法(accessor)。例如

class C def name @name end def name=(str) # name 后面不能有空格! @name = str end end c = C.new c.name = '山田太郎' p c.name #=> "山田太郎"

另外,您还可以使用Module#attr、attr_reader、 attr_writer、attr_accessor等来完成这种简单的方法定义。例如,您可以这样来重写上面的类定义。

class C attr_accessor :name end

若您不愿定义访问方法,却想使用实例变量时,可以使用Object#instance_eval。

5.5 private和protected有什么不同?

private意味着只能使用函数形式来调用该方法,而不能使用被调形式。所以,您只能在本类或其子类中调用private方法。

protected也是一样,只能用在本类及其子类中。但是您既可以使用函数形式又可以使用被调形式来调用它。

在封装方法时,该功能是必不可少。

5.6 能不能将实例变量变成public类型的变量?

无法让变量变成public类型的变量。在Ruby中访问实例变量时,需要使用访问方法。例如

class Foo def initialize(str) @name = str end def name return @name end end

但是每次都这么写的话,未免有些繁琐。因此可以使用attr_reader、attr_writer、 attr_accessor等方法来完成这些简单的方法定义。

class Foo def initialize(str) @name = str end attr_reader :name # 其效果等同于下面的代码。 # def name # return @name # end end foo = Foo.new("Tom") print foo.name, "\n" # Tom

您还可以使用attr_accessor来同时定义写入的方法。

class Foo def initialize(str) @name = str end attr_accessor :name # 其效果等同于下面的代码。 # def name # return @name # end # def name=(str) # @name = str # end end foo = Foo.new("Tom") foo.name = "Jim" print foo.name, "\n" # Jim

若只想定义写入方法的话,可以使用attr_writer。

5.7 怎样指定方法的可见性?

首先 Ruby把那些只能以函数形式(省略被调的形式)来调用的方法叫做private方法。请注意,这里的private定义与C++以及Java中的定义不同。

若将方法设为private类型之后,就不能在其它的对象中调用该方法了。因此,若您只想在本类或其子类中调用某方法时, 就可以把它设为private类型。

您可以这样把方法设为private类型。

class Foo def test print "hello\n" end private :test end foo = Foo.new foo.test #=> test.rb:9: private method `test' called for #<Foo:0x400f3eec>
(Foo)

您可以使用private_class_method将类方法变为private类型。

class Foo def Foo.test print "hello\n" end private_class_method :test end Foo.test #=> test.rb:8: private method `test' called for Foo(Class)

同理,您可以使用public、public_class_method将方法设为public类型。

在默认情况下,类中的方法都被定义成public类型(initialize除外),而顶层中的方法会被定义成private类型。

5.8 方法名可以用大写字母开头吗?

可以。但要注意:即使方法调用中不带参数,也不能省略方法名后的空括号。

5.9 为什么使用super时会出现ArgumentError?

在方法定义中调用super时,会把所有参数都传给上层方法,若参数个数不符合其要求,就会引发ArgumentError。因此,若参数个数不合时,应该自己指定参数然后再调用super。

5.10 如何调用上2层的同名方法?

super只能调用上1层的同名方法。若想调用2层以上的同名方法时,需要事先对该上层方法进行alias操作。

5.11 重定义内部函数时,如何调用原来的函数?

可以在方法定义中使用super。进行重定义之前,使用alias就可以保住原来的定义。也可以把它当作Kernel的特殊方法来进行调用。

5.12 何谓破环性的方法?

就是能修改对象内容的方法,常见于字符串、数组或哈希表中。一般是这样的:存在两个同名的方法,一个会拷贝原对象并返回副本;一个会直接修改原对象的内容,并返回修改后的对象。通常后者的方法名后面带有!,它就是破坏性的方法。但是有些不带!的方法也是具有破环性的,如String#concat等等。

5.13 那些情况下会产生副作用?

若在方法中对实参对象使用了破环性的方法的时候,就会产生副作用。

def foo(str) str.sub!(/foo/, "baz") end obj = "foo" foo(obj) print obj #=> "baz"

此时,参数对象的内容被修改。另一方面,如果在程序中确有必要的话,也会对某对象发送具有副作用的消息,那就另当别论了。

5.14 能让方法返回多个值吗?

在Ruby中确实只能指定一个方法返回值,但若使用数组的话,就可以返回多个值了。

return 1, 2, 3

上例中,传给return的列表会被当作数组处理。这与下面的代码可谓是异曲同工。

return [1, 2, 3]

另外,若使用多重赋值的话,则可以达到返回多个值的效果。例如

def foo return 20, 4, 17 end a, b, c = foo print "a:", a, "\n" #=> a:20 print "b:", b, "\n" #=> b:4 print "c:", c, "\n" #=> c:17

您也可以这样处理。

延伸阅读

文章来源于领测软件测试网 https://www.ltesting.net/


关于领测软件测试网 | 领测软件测试网合作伙伴 | 广告服务 | 投稿指南 | 联系我们 | 网站地图 | 友情链接
版权所有(C) 2003-2010 TestAge(领测软件测试网)|领测国际科技(北京)有限公司|软件测试工程师培训网 All Rights Reserved
北京市海淀区中关村南大街9号北京理工科技大厦1402室 京ICP备2023014753号-2
技术支持和业务联系:info@testage.com.cn 电话:010-51297073

软件测试 | 领测国际ISTQBISTQB官网TMMiTMMi认证国际软件测试工程师认证领测软件测试网