- 相關(guān)推薦
Ruby專業(yè)面試試題
一、介紹一下Ruby的特點(diǎn)
Ruby是一種功能強(qiáng)大的面向?qū)ο蟮哪_本語言,可以使用它方便快捷地進(jìn)行面向?qū)ο蟪绦蛟O(shè)計(jì)。與Perl類似,而且Ruby具有強(qiáng)大的文本處理功能,使文本處理變得簡單。此外還可以方便地使用C語言來擴(kuò)展Ruby的功能。
若您曾經(jīng)“想要一種簡單的面向?qū)ο蟮恼Z言”,或者認(rèn)為“Perl的功能雖然好用,但它的語法真讓人受不了”,又或者覺得“LISP系列語言的思想不錯,但到處都是括號真讓人討厭,最起碼算式應(yīng)該按照通常的樣式書寫”。那么,Ruby或許能讓您滿意。
歸納起來,Ruby有以下優(yōu)點(diǎn):
1、解釋型執(zhí)行,方便快捷
Ruby是解釋型語言,其程序無需編譯即可執(zhí)行。
2、語法簡單、優(yōu)雅
語法比較簡單,類似Algol系語法。
3、完全面向?qū)ο?/p>
Ruby從一開始就被設(shè)計(jì)成純粹的面向?qū)ο笳Z言,因此所有東西都是對象,例如整數(shù)等基本數(shù)據(jù)類型。
4、內(nèi)置正則式引擎,適合文本處理
Ruby支持功能強(qiáng)大的字符串操作和正則表達(dá)式檢索功能,可以方便的對字符串進(jìn)行處理。
5、自動垃圾收集
具有垃圾回收(Garbage Collect,GC)功能,能自動回收不再使用的對象。不需要用戶對內(nèi)存進(jìn)行管理。
6、跨平臺和高度可移植性
Ruby支持多種平臺,在Windows, Unix, Linux, MacOS上都可以運(yùn)行。Ruby程序的可移植性非常好,絕大多數(shù)程序可以不加修改的在各種平臺上加以運(yùn)行。
7、有優(yōu)雅、完善的異常處理機(jī)制
Ruby提供了一整套異常處理機(jī)制,可以方便優(yōu)雅地處理代碼處理出錯的情況。
8、擁有很多高級特性
Ruby擁有很多高級特性,例如操作符重載、Mix-ins、特殊方法等等,是用這些特性可以方便地完成各種強(qiáng)大的功能。
同時(shí),由于是解釋型語言,Ruby也有下列缺點(diǎn):
1、解釋型語言,所以速度較慢
2、靜態(tài)檢查比較少
二、介紹一下Ruby的多線程處理
Ruby的多線程是用戶級多線程,這樣使得Ruby的多線程移植非常容易,你并不需關(guān)心具體的操作系統(tǒng);這樣做也使線程容易控制,程序不容易產(chǎn)生死鎖這類嚴(yán)重的線程問題。
但是同時(shí),由于Ruby的多線程并不是真正意義上的操作系統(tǒng)級多線程,不管代碼使用了多少個Thread類的實(shí)例,都只會在啟動解釋器這一個進(jìn)程內(nèi)執(zhí)行,由Ruby解釋器進(jìn)行具體的線程切換管理,其效率要低于由操作系統(tǒng)管理線程的效率,且不能使用多個CPU。
在Ruby中同時(shí)做多件事最簡單的方式就是使用Thread類,Thread類提供了一種高效和輕量級的手段來同時(shí)處理多件任務(wù)。
Thread類由Ruby解釋器具體實(shí)現(xiàn),提供了一種同時(shí)處理多個任務(wù)的方法, Thread類實(shí)現(xiàn)的并不是操作系統(tǒng)級多線程。
Ruby多線程的優(yōu)點(diǎn)和缺點(diǎn)同樣明顯,缺點(diǎn)是效率不如操作系統(tǒng)級多線程,不能使用多個CPU,但其優(yōu)點(diǎn)也很明顯,即可移植性很高。這就需要設(shè)計(jì)人員綜合考慮。
三、、Ruby如何實(shí)現(xiàn)動態(tài)方法調(diào)用
在Ruby中,有多種方法可以實(shí)現(xiàn)方法的動態(tài)調(diào)用。
1. 使用send方法
第一種實(shí)現(xiàn)動態(tài)方法調(diào)用是使用send方法,send方法在Object類中定義,方法的第一個參數(shù)是一個符號用來表示所要調(diào)用的方法,后面則是所調(diào)用方法需要的參數(shù)。
“This is a dog1″.send(:length) => 14
上面的代碼中通過send方法去對一個字符串執(zhí)行l(wèi)ength操作,返回字符串的長度。
class TestClass
def hello(*args)
”Hello ” + args.join(‘ ‘)
end
end
a = TestClass.new
puts a.send :hello, “This”, “is”, “a”, “dog!”
執(zhí)行結(jié)果為:
Hello This is a dog!
2. 使用Method類和UnboundMethod類
另一種實(shí)現(xiàn)動態(tài)方法調(diào)用是使用Object類的method方法,這個方法返回一個Method類的對象。我們可以使用call方法來執(zhí)行方法調(diào)用。
test1 = “This is a dog1″.method(:length)
test1.call => 14
class Test
def initialize(var)
@var = var
end
def hello()
”Hello, @var = #{@var}”
end
end
k = Test.new(10)
m = k.method(:hello)
m.call #=> “Hello, @iv = 99″
l = Test.new(‘Grant’)
m = l.method(“hello”)
m.call #=> “Hello, @iv = Fred”
可以在使用對象的任何地方使用method對象,當(dāng)調(diào)用call方法時(shí),參數(shù)所指明的方法會被執(zhí)行,這種行為有些像C語言中的函數(shù)指針。你也可以把method對象作為一個迭代器使用。
def square(a)
a*a
end
mObj = method(:square)
[1, 2, 3, 4].collect(&mObj) => [1 4 9 16]
Method對象都是和某一特定對象綁定的,也就是說你需要通過某一對象使用Method對象。你也可以通過UnboundMethod類創(chuàng)建對象,然后再把它綁定到某個具體的對象中。如果UnboundMethod對象調(diào)用時(shí)尚未綁定,則會引發(fā)異常。
class Double
def get_value
2 * @side
end
def initialize(side)
@side = side
end
end
a = Double.instance_method(:get_value) #返回一個UnboundMethod對象
s = Double.new(50)
b = a.bind(s)
puts b.call
執(zhí)行結(jié)果為:
100
看下面一個更具體的例子:
class CommandInterpreter
def do_2() print “This is 2\n”; end
def do_1() print “This is 1\n”; end
def do_4() print “This is 4\n”; end
def do_3() print “This is 3\n”; end
Dispatcher = {
?2 => instance_method(:do_2),
?1 => instance_method(:do_1),
?4 => instance_method(:do_4),
?3 => instance_method(:do_3)
}
def interpret(string)
string.each_byte {|i| Dispatcher[i].bind(self).call }
end
end
interpreter = CommandInterpreter.new
interpreter.interpret(’1234′)
執(zhí)行結(jié)果為:
This is 1
This is 2
This is 3
This is 4
3. 使用eval方法
我們還可以使用eval方法實(shí)現(xiàn)方法動態(tài)調(diào)用。eval方法在Kernel模塊中定義,有多種變體如class_eval,module_eval,instance_eval等。Eval方法將分析其后的字符串參數(shù)并把這個字符串參數(shù)作為Ruby代碼執(zhí)行。
str = “Hello”
eval “str + ‘ World!’” => Hello World!
sentence = %q{“This is a test!”.length}
eval sentence => 15
當(dāng)我們在使用eval方法時(shí),我們可以通過eval方法的第二個參數(shù)指明eval所運(yùn)行代碼的上下文環(huán)境,這個參數(shù)可以是Binding類對象或Proc類對象。Binding類封裝了代碼在某一環(huán)境運(yùn)行的上下文,可以供以后使用。
class BindingTest
def initialize(n)
@value = n
end
def getBinding
return binding() #使用Kernel#binding方法返回一個Binding對象
end
end
obj1 = BindingTest.new(10)
binding1 = obj1.getBinding
obj2 = BindingTest.new(“Binding Test”)
binding2 = obj2.getBinding
puts eval(“@value”, binding1) #=> 10
puts eval(“@value”, binding2) #=> Binding Test
puts eval(“@value”) #=> nil
可以看到上述代碼中,@value在binding1所指明的上下文環(huán)境中值為10,在binding2所指明的上下文環(huán)境中值為Binding Test。當(dāng)eval方法不提供binding參數(shù)時(shí),在當(dāng)前上下文環(huán)境中@value并未定義,值為nil。