ruby方法常見問題

發表于:2007-07-04來源:作者:點擊數: 標簽:
5.1 向對象發出消息之后,將按照什么順序來搜索要執行的方法? 將依次搜索特殊方法、本類中定義的方法和超類(包括Mix-in進來的模塊。寫成 類名.ancestors。)中定義的方法,并執行所找到的第一個方法。若沒有找到方法時,將按照同樣的順序來搜索method_missing
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 可以在外部使用對象的實例變量嗎?

不能直接使用。若想操作實例變量,必須事先在對象中定義操作實例變量的方法(aclearcase/" target="_blank" >ccessor)。例如

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

您也可以這樣處理。

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97