Skip to content
This repository
branch: master
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 191 lines (153 sloc) 5.35 kb

讓我們建立一個 greeter 物件來使用:

irb(main):035:0> g = Greeter.new("Pat") => # irb(main):036:0> g.say_hi Hi Pat! => nil irb(main):037:0> g.say_bye Bye Pat, come back soon. => nil

一旦建立了 g 物件,它就會記得它的名字是 Pat。嗯,但是我們如何拿到這個名字的值呢?

irb(main):038:0> g.@name SyntaxError: compile error (irb):52: syntax error from (irb):52

啊,這樣不行。

揭開物件的面紗

物件中的實例變數(Instance variables)是隱藏的。雖然可以透過檢查(inspect)物件看到這個變數,不過 Ruby 採用了物件導向的思維(譯註: 即封裝),內部屬性資料基本上是隱藏起來的。

到底 Greeter 物件有哪些方法呢?

irb(main):039:0> Greeter.instance_methods => ["method", "send", "object_id", "singleton_methods", "__send__", "equal?", "taint", "frozen?", "instance_variable_get", "kind_of?", "to_a", "instance_eval", "type", "protected_methods", "extend", "eql?", "display", "instance_variable_set", "hash", "is_a?", "to_s", "class", "tainted?", "private_methods", "untaint", "say_hi", "id", "inspect", "==", "===", "clone", "public_methods", "respond_to?", "freeze", "say_bye", "__id__", "=~", "methods", "nil?", "dup", "instance_variables", "instance_of?"]

哇。有這麼多。我們不是只定義了兩個方法,怎麼回事呢? 這裡列出的是*所有* Greeter 物件的方法,因此也包括了它所繼承的類別的方法。如果我們只需要 Greeter 自己的方法,可以傳入一個 false 參數,表示我們不希望包括父類別的方法。

irb(main):040:0> Greeter.instance_methods(false) => ["say_bye", "say_hi"]

看起來好多了。讓我們看看 greeter 物件對哪些方法有反應?

irb(main):041:0> g.respond_to?("name") => false irb(main):042:0> g.respond_to?("say_hi") => true irb(main):043:0> g.respond_to?("to_s") => true

它知道 say_hito_s (意思是轉換成字串,這是每個物件都有的方法),但是不知道 name 這個方法。

變更類別,永不嫌晚

那麼要怎麼能夠讀取或修改名字呢? Ruby 提供了一個簡單的方式來讓你存取物件的變數:

irb(main):044:0> class Greeter irb(main):045:1> attr_accessor :name irb(main):046:1> end => nil

在 Ruby 裡你可以再度打開一個類別然後修改它。這個改變會對之後產生的物件,甚至是已經產生的物件產生即時效果。所以,我們來建立一個新的物件試試看 @name 屬性。

irb(main):047:0> g = Greeter.new("Andy") => # irb(main):048:0> g.respond_to?("name") => true irb(main):049:0> g.respond_to?("name=") => true irb(main):050:0> g.say_hi Hi Andy! => nil irb(main):051:0> g.name="Betty" => "Betty" irb(main):052:0> g => # irb(main):053:0> g.name => "Betty" irb(main):054:0> g.say_hi Hi Betty! => nil

attr_accessor 會定義兩個新的方法,@name@ 用來取值,而 name= 用來給值。

可以歡迎任何東西的 MegaGreeter!

這個 greeter 玩膩了,它一次只能處理一個人。要如何能夠有 MegaGreeter 可以不只歡迎這個世界,還可以歡迎不同人,甚至是一群人呢?

接著讓我們開一個新檔案來撰寫 Ruby 程式吧,互動式的 IRB 不適合撰寫較長的程式。

要離開 IRB 請輸入 “quit” 或 “exit” 或按下 Control-D。

#!/usr/bin/env ruby class MegaGreeter attr_accessor :names # 初始化這個物件 def initialize(names = "World") @names = names end # 向每個人說 hi def say_hi if @names.nil? puts "..." elsif @names.respond_to?("each") # @names 是可以迭代的陣列容器 @names.each do |name| puts "Hello #{name}!" end else puts "Hello #{@names}!" end end # 向每個人說 bye def say_bye if @names.nil? puts "..." elsif @names.respond_to?("join") # 用逗號將陣列中的元素串接成一個字串 puts "Goodbye #{@names.join(", ")}. Come back soon!" else puts "Goodbye #{@names}. Come back soon!" end end end if __FILE__ == $0 mg = MegaGreeter.new mg.say_hi mg.say_bye # 變更成 "Zeke" mg.names = "Zeke" mg.say_hi mg.say_bye # 變更成一個名字的陣列 mg.names = ["Albert", "Brenda", "Charles", "Dave", "Englebert"] mg.say_hi mg.say_bye # 變更成 nil mg.names = nil mg.say_hi mg.say_bye end

把這個檔案存成 “ri20min.rb”,然後輸入 “ruby ri20min.rb” 來執行它。您應該可以看到輸出是:

Hello World! Goodbye World. Come back soon! Hello Zeke! Goodbye Zeke. Come back soon! Hello Albert! Hello Brenda! Hello Charles! Hello Dave! Hello Englebert! Goodbye Albert, Brenda, Charles, Dave, Englebert. Come back soon! ... ...

這個最後的範例有許多新東西,讓我們來"仔細瞧瞧":../4/。

Something went wrong with that request. Please try again.