IT面试笔试题全集_Ruby篇_Rain系列_第1页
IT面试笔试题全集_Ruby篇_Rain系列_第2页
IT面试笔试题全集_Ruby篇_Rain系列_第3页
IT面试笔试题全集_Ruby篇_Rain系列_第4页
IT面试笔试题全集_Ruby篇_Rain系列_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、it面试笔试题全集_史上最全_ruby篇_rain系列ruby如何实现动态方法调用?_追雨制作 在ruby中,有多种方法可以实现方法的动态调用。1. 使用send方法第一种实现动态方法调用是使用send方法,send方法在object类中定义,方法的第一个参数是一个符号用来表示所要调用的方法,后面则是所调用方法需要的参数。#8220;this is a dog1#8243;.send(:length)= 14上面的代码中通过send方法去对一个字符串执行length操作,返回字符串的长度。class testclassdef hello(*args)hello + args.join(#821

2、7; #8216;)endenda = testclass.newputs a.send :hello, #8220;this, #8220;is, #8220;a, #8220;dog!执行结果为:hello this is a dog!2. 使用method类和unboundmethod类另一种实现动态方法调用是使用object类的method方法,这个方法返回一个method类的对象。我们可以使用call方法来执行方法调用。test1 = #8220;this is a dog1#8243;.method(:length)test1.call= 14class testdef initi

3、alize(var)var = varenddef hello()hello, var = #varendendk = test.new(10)m = k.method(:hello)m.call #= #8220;hello, iv = 99#8243;l = test.new(#8217;grant#8217;)m = l.method(hello)m.call #= #8220;hello, iv = fred可以在使用对象的任何地方使用method对象,当调用call方法时,参数所指明的方法会被执行,这种行为有些像语言中的函数指针。你也可以把method对象作为一个迭代器使用。def

4、square(a)a*aendmobj = method(:square)1, 2, 3, 4.collect(amp;mobj)=1 4 9 16method对象都是和某一特定对象绑定的,也就是说你需要通过某一对象使用method对象。你也可以通过unboundmethod类创建对象,然后再把它绑定到某个具体的对象中。如果unboundmethod对象调用时尚未绑定,则会引发异常。class doubledef get_value2 * sideenddef initialize(side)side = sideendenda = double.instance_method(:get_va

5、lue) #返回一个unboundmethod对象s = double.new(50)b = a.bind(s)puts b.call执行结果为:100看下面一个更具体的例子:class commandinterpreterdef do_2() print #8220;this is 2n; enddef do_1() print #8220;this is 1n; enddef do_4() print #8220;this is 4n; enddef do_3() print #8220;this is 3n; enddispatcher = ?2 = instance_method(:d

6、o_2),?1 = instance_method(:do_1),?4 = instance_method(:do_4),?3 = instance_method(:do_3)def interpret(sing)sing.each_byte |i| dispatcheri.bind(self).call endendinterpreter = commandierpret(#8217;1234#8242;)执行结果为:this is 1this is 2this is 3this is 43. 使用eval方法我们还可以使用eval方

7、法实现方法动态调用。eval方法在kernel模块中定义,有多种变体如class_eval,module_eval,instance_eval等。eval方法将分析其后的字符串参数并把这个字符串参数作为ruby代码执行。s = #8220;helloeval #8220;s + #8216; world!#8217;= hello world!sentence = %qthis is a test!.lengtheval sentence= 15当我们在使用eval方法时,我们可以通过eval方法的第二个参数指明eval所运行代码的上下文环境,这个参数可以是binding类对象或proc类对象

8、。binding类封装了代码在某一环境运行的上下文,可以供以后使用。class bindingtestdef initialize(n)value = nenddef getbindingreturn binding()#使用kernel#binding方法返回一个binding对象endendobj1 = bindingtest.new(10)binding1 = obj1.getbindingobj2 = bindingtest.new(binding test)binding2 = obj2.getbindingputs eval(value, binding1)#= 10puts ev

9、al(value, binding2)#= binding testputs eval(value)#= nil可以看到上述代码中,value在binding1所指明的上下文环境中值为10,在binding2所指明的上下文环境中值为binding test。当eval方法不提供binding参数时,在当前上下文环境中value并未定义,值为nil。 ruby如何进行文件操作? 请用代码表示_追雨制作 ruby使用file类来操作文件,可以通过file.new来创建一个file类的实例并打开这个文件。file = file.new(testfile, #8220;r)# #8230; proce

10、ss the filefile.closetestfile是想要操作的文件名,”r”说明了文件的操作模式为读取。可以使用”w”表示写入,”rw”表示读写。最后要记得关闭打开的文件,确保所有被缓冲的数据被写入文件,所有相关的资源被释放。也可以使用file.open来打开文件,open和new的不同是open可以使用其后的代码块而new方法则返回一个file类的实例。file.open(testfile, #8220;r) do |file|# #8230; process the fileendopen操作的另一个优点是处理了异常,如果处理一个文件发生错误抛出了异常的话,那么open操作会自动关

11、闭这个文件,下面是open操作的大致实现:class filedef file.open(*args)result = f = file.new(*args)if block_given?beginresult = yield fensuref.closeendendreturn resultendend对于文件的路径,ruby会在不同的操作系统间作转换。例如,在windows下,/ruby/sample/test.rb会被转化为rubysampletest.rb。当你使用字符串表示一个windows下的文件时,请记住使用反斜线先转义:“c:rubysampletest.rb”也可以使用fil

12、e:separator表示不同系操作统的路径分割符。 ruby如何创建一个线程?_追雨制作 可以使用thread.new方法去创建一个线程,可以随后代码块中列出线程执行的代码:x = thread.new sleep 0.1; print #8220;x; print #8220;y; print #8220;z a = thread.new print #8220;a; print #8220;b; sleep 0.2; print #8220;c 执行结果为:ab上面的示例程序中使用thread.new创建了二个线程,线程随即开始运行。但是运行结果很奇怪,为什么程序运行结果是“ab”呢?我

13、们预期的执行结果应该是 “abxyzc”。当ruby程序执行完毕的时候,他会杀掉所有的线程,不管其它的线程的运行状态如何。如果没有使用join方法,那么主程序执行完毕后会把所有没有执行完毕的线程杀掉。上面的实例程序中,当主程序运行完毕时,两个线程都没有运行结束就被中止掉了。我们可以使用join方法来让主程序等待某个特定线程结束,对每一个线程使用join方法,可以确保在程序结束前所有的线程可以运行完毕。x = thread.new sleep 0.1; print #8220;x; print #8220;y; print #8220;z a = thread.new print #8220;a

14、; print #8220;b; sleep 0.2; print #8220;c x.joina.join我们使用thread.new方法创建两个新的线程并开始运行, 然后使用join方法等待线程结束。执行结果为:abxyzc可以看到通过使用join方法等待线程结束,程序运行结果和我们预期结果相符。另一个例子:x = thread.new sleep 0.1; print #8220;x; print #8220;y; print #8220;z a = thread.new sleep 0.1; print #8220;a; print #8220;b; sleep 0.2; print

15、#8220;c 执行没有任何输出,因为主程序执行完毕杀死两个线程的时候这两个线程没有运行到输出语句。也可以给join方法添加时间用来指明最大等待时间。如果超时join返回nil。x = thread.new sleep 0.1; print #8220;x; print #8220;y; print #8220;z a = thread.new sleep 0.1; print #8220;a; print #8220;b; sleep 10; print #8220;c x.join(5)a.join(5)执行结果为:abxyz上面的例子中对于每一个线程的最大等待时间是5秒,由于a线程需要执

16、行10秒以上,所以a线程没有运行完毕程序就将返回。 介绍一下ruby的多线程处理_追雨制作 ruby的多线程是用户级多线程,这样使得ruby的多线程移植非常容易,你并不需关心具体的操作系统;这样做也使线程容易控制,程序不容易产生死锁这类严重的线程问题。但是同时,由于ruby的多线程并不是真正意义上的操作系统级多线程,不管代码使用了多少个thread类的实例,都只会在启动解释器这一个进程内执行,由ruby解释器进行具体的线程切换管理,其效率要低于由操作系统管理线程的效率,且不能使用多个cpu。在ruby中同时做多件事最简单的方式就是使用thread类,thread类提供了一种高效和轻量级的手段来

17、同时处理多件任务。thread类由ruby解释器具体实现,提供了一种同时处理多个任务的方法, thread类实现的并不是操作系统级多线程。ruby多线程的优点和缺点同样明显,缺点是效率不如操作系统级多线程,不能使用多个cpu,但其优点也很明显,即可移植性很高。这就需要设计人员综合考虑。 既然说ruby中一切都是对象,那么ruby中类也是对象吗?_追雨制作 没错,类也是对象,这是ruby和c+/java的一个显著不同,在c+/java中,类仅仅是一个数据抽象,并没有类也是对象这样的概念。而在ruby中存在着元类的概念,类也是对象,所有类都是元类的实例对象。和c+/java相比,ruby的面向对象

18、程度更高。可以看到,类对象和实例对象一样有自己的ojbect_id,你可以象调用一个实例对象的方法一样去用它去调用类方法。所有类对象的类是class类,oject类是所有类的基类。irb(main):003:0 object.class= classirb(main):004:0 object.superclass= nil ruby中的保护方法和私有方法与一般面向对象程序设计语言的一样吗?_追雨制作 ruby中的保护方法和私有方法与一般面向对象程序设计语言的概念有所区别,保护方法的意思是方法只能方法只能被定义这个方法的类自己的对象和子类的对象访问,私有方法只能被对象自己访问。class te

19、stdef method1 #默认为公有方法endprotected#保护方法def method2endprivate#私有方法def method3endpublicdef test_protected(arg) #arg是test类的对象arg.method2 #正确,可以访问同类其他对象的保护方法enddef test_private(arg)#arg是test类的对象arg.method3 #错误,不能访问同类其他对象的私有方法endendobj1 = test.newobj2 = test.newobj1.test_protected(obj2)obj1.test_private(

20、obj2)可以看到,和c+/java相比,ruby提供了更好的封装性。 解释一下ruby中的特殊方法与特殊类?_追雨制作 特殊方法是指某实例所特有的方法。一个对象有哪些行为由对向所属的类决定,但是有时候,一些特殊的对象有何其他对象不一样的行为,在多数程序设计语言中,例如c+和java,我们必须定义一个新类,但在ruby中,我们可以定义只从属于某个特定对象的方法,这种方法我们成为特殊方法(singleton method)。class singletontestdef infoputs #8220;this is this is singletontest methodendendobj1 =

21、singletontest.newobj2 = singletontest.newdef puts #8220;this is obj2#8243;执行结果为:this is this is singletontest methodthis is obj2有时候,我们需要给一个对象定义一系列的特殊方法,如果按照前面的方法,那么只能一个一个定义:def obj2.singleton_method1enddef obj2.singleton_method2enddef obj2.singleton_method3enddef obj2.s

22、ingleton_methodnend这样做非常繁复麻烦,而且无法给出一个统一的概念模型,因此ruby提供了另外一种方法,class objendobj是一个具体的对象实例,class 代表它的特殊类。class singletontestdef meth1puts #8220;this is meth1#8243;enddef meth2puts #8220;this is meth2#8243;endendobj1 = singletontest.newobj2 = singletontest.newclass obj2def meth1puts #8220;this is obj2#82

23、17;s meth1#8243;enddef meth2puts #8220;this is obj2#8217;s meth2#8243;endendobj1.meth1obj1.meth2obj2.meth1obj2.meth2执行结果为:this is meth1this is meth2this is obj2#8217;s meth1this is obj2#8217;s meth2 ruby如何进行集成操作?ruby能进行多重继承吗?_追雨制作 ruby继承的语法很简单,使用 即可。ruby语言只支持单继承,每一个类都只能有一个直接父类。这样避免了多继承的复杂度。但同时,ruby提

24、供了mixin的机制可以用来实现多继承。可以使用super关键字调用对象父类的方法,当super省略参数时,将使用当前方法的参数来进行调用。 介绍一下ruby中的对象,属性和方法_追雨制作 在ruby中,除去内部类的对象以外,通常对象的构造都是动态确定的。某对象的性质由其内部定义的方法所决定。看下面的例子,我们使用new方法构造一个新的对象,class persondef initialize(name, gender, age)name = namegender = genderage = ageendendpeople = person.new(#8217;tom#8217;, #8216

25、;male#8217;, 15)我们可以使用person.new方法来创建一个person类的实例对象。以打头的变量是实例变量,他们从属于某一实例对象,ruby中实例变量的命名规则是变量名以开始,您只能在方法内部使用它。initialize方法使对象变为“就绪”状态,initialize方法是一个特殊的方法,这个方法在构造实例对象时会被自动调用。对实例进行初始化操作时,需要重定义initialize方法。类方法new的默认的行为就是对新生成的实例执行initialize方法,传给new方法的参数会被原封不动地传给initialize方法。另外,若带块调用时,该块会被传给initialize方法

26、。因此,不必对new方法进行重定义。在ruby中,只有方法可以操作实例变量,因此可以说ruby中的封装是强制性的。在对象外部不可以直接访问,只能通过接口方法访问。class persondef namenameenddef gendergenderenddef ageageendendpeople = person.new(#8217;tom#8217;, #8216;male#8217;, 15)puts puts people.genderputs people.age输出结果为:tommale15在ruby中,一个对象的内部属性都是私有的。 上面的代码中,我们定义了

27、方法name,gender,age三个方法用来访问person类实例对象的实例变量。注意name,gender,age访问只能读取相应实例变量,而不能改变它们的值。我们也可以用成员变量只读控制符at_reader来达到同样的效果。class personat_reader :name, :gender, :ageend类似地,我们可以定义方法去改变成员变量的值。class persondef name=(name)name=nameenddef gender=(gender)gender=genderenddef age=(age)age=ageendendpeople = person.ne

28、w(#8217;tom#8217;, #8216;male#8217;, 15)= #8220;henrypeople.gender= #8220;malepeople.age= 25也可以用成员变量写控制符at_writer来达到同样的效果。class personat_writer :name, :gender, :ageend我们也可以使用at_accessor来说明成员变量既可以读,也可以写。class personat_accessor :name, :gender, :ageend也可以使用at控制符来控制变量是否可读写。at 只能带一个符号参数, 第二个参数

29、是一个 bool 参数,用于指示是否为符号参数产生写方法。它的默认值是 false,只产生读方法,不产生写方法。class personat :name, ue#读写at :gender, ue#读写at :age, ue#读写at :id, false #只读end注意at_reader,at_writer,at_accessor和at不是语言的关键字,而是module模块的方法。class testat_accessor :valueendputs test.instance_methods test.superclass.public_methods执行结果为:valuevalue=上面

30、代码中,我们使用test.instance_methods得到test类所有的实例方法,使用test.superclass.public_methods得到test父类所有的实例方法,然后相减就得到test类不包含父类的所有的实例方法。由于instance_methods方法返回值为一个array,所以我们作差值运算。也可以重定义方法,重定义一个方法时,新的定义会覆盖原有的定义。下面的例子重定义类中的方法meth1,class testdef meth1puts #8220;this is meth1#8243;endenda = test.newa.meth1class testdef me

31、th1puts #8220;this is new meth1#8243;endenda.meth1执行结果为:this is meth1this is new meth1重定义同一个类时,意味着对原有定义进行补充,不会覆盖原来的定义。而重定义方法时,则会覆盖原有定义。我们可以使用self标识本身,self和java中的this有些类似,代表当前对象。class persondef initialize(name, gender, age)name = namegender = genderage = ageenddef (other)self.age other.ageendend 方法通常

32、意思为比较,返回值为-1,0或1分别表示小于,等于和大于。 ruby如何定义一个类?_追雨制作 类是对具有同样属性和同样行为的对象的抽象,ruby中类的声明使用class关键字。定义类的语法如下,class classnamedef method_name(variables)#some codeendend类的定义要在classend之间,在上面的格式中,classname是类名,类名必须以大写字母开始,也就是说类名要是个常量。看下面的例子:class persondef initialize(name, gender, age)name = namegender = genderage =

33、 ageendend若某个类已经被定义过,此时又用相同的类名进行类定义的话,就意味着对原有的类的定义进行追加。class testdef meth1puts #8220;this is meth1#8243;endendclass testdef meth2puts #8220;this is meth2#8243;endend在test类中,原有meth1方法,我们又追加了meth2方法,这时候,对于test类的对象,meth1和meth2同样可用。 为什么说ruby是一种真正的面向对象程序设计语言?_追雨制作 在ruby中,所操作的一切都是对象,操作的结果也是对象。很多语言都说自己是面向对

34、象的,但是他们往往对面向对象的解释都一样,大多是以自己特有的方式来解释什么是面向对象,而在实际情况中,这些面向对象语言又采用了很多非面向对象的做法。以 java 为例:如果你想取一个数字取绝对值,java 的做法是:int num = math.abs(-99);也就是将一个数值传递给 math 类的一个静态函数 abs 处理。为什么这么做?因为在 java 中,数值是基本类型不是类。而在 ruby 中,任何事物都是对象,也就是说,数字99就是对象,取绝对值这样的操作应该属于数字本身,所以ruby的做法就是:c = -99.abs 给定一个时间点,希望得到其他时间点_追雨制作 问题:给定一个时

35、间点,希望得到其他时间点参考答案:ruby 的所有时间对象都可像数字一样用在值域中。date和datetime对象按天递增,而time对象按秒递增: require #8216;date#8217; (date.new(1776, 7, 2).date.new(1776, 7, 4).each |x| puts x # 1776-07-02 # 1776-07-03 # 1776-07-04span = datetime.new(1776, 7, 2, 1, 30, 15).datetime.new(1776, 7, 4, 7, 0, 0) span.each |x| puts x # 1776-07-02t01:30:15z # 1776-07-03t01:30:15z # 1776-07-04t01:30:15z(time.at(100).time.at(102).each |x| puts x # wed dec 31 19:01:40 est 1969 # wed dec 31 19:01:41 est 1969 # wed dec 31 19:01:42 est 1969ruby 的date类定义了step和upto两种方便的由数字使用的迭代器: t

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论