Skip to content

Instantly share code, notes, and snippets.

@fokayx
Last active August 29, 2015 14:23
Show Gist options
  • Select an option

  • Save fokayx/6e0e621289d0a73117d2 to your computer and use it in GitHub Desktop.

Select an option

Save fokayx/6e0e621289d0a73117d2 to your computer and use it in GitHub Desktop.
Ruby Explained: Objects and Methods

##Ruby Explained: Objects and Methods @Erik Trautman

"Everything in Ruby is an Object" is something you'll hear rather frequently. "Pretty much everything else is a method" could also be said.

Ruby 所有東西都是物件,也可以這麼說,幾乎一切都是方法。

今天的目標是能初步了解Ruby的核心概念。在Ruby中所有東西都是物件,每一個物件都有一個類別,每個類別則付予給物件許多方法,可以用來做點什麼事,或者問些問題。物件導向(object-oriented)給予 Ruby超乎想像的權力,讓程式人員的人生輕鬆許多。

思考一下:在Ruby中的任何"東西",不只是眼睛所看到的那樣,例如數字"12",對Ruby來說"12"除了是個數字,他還是個物件,能讓你做許多有趣的操作,例如進行加減乘除或者問他問題:

> 12.class
=> Fixnum

> 12.integer?
=> true

> 12 + 3
=> 15

Ruby賦予所有物件(Objects)一大串的方法(Methods),方法的呼叫是:物件.方法名(object.methodname),例如:使用methods這個方法,就能取得所有和該物件有關的方法。

> 12345.methods
=> #就會回傳"12345"這個物件能使用的所有方法

"12345"的所有方法中也包含基本的運算符號"+"、"-"、"*"、"/",所以原本也得寫成12345.+123或者12345./5,感覺有點囉嗦,還好Ruby做了簡化,使用基本運算符號可以省略".",直接輸入12345+123也是可以運行的。

有些屬於檢查是否/真假(true/false)的方法,通常會在方法名最後加上一個問號(?),例如:is_a?,這個方法是用於檢查該物件是否是某個類型。::class則會告訴你該物件屬於何種類別(class):

> 1.is_a?Integer
=> true   # 1是整數嗎?
> "hihi".is_a?Integer
=> false
> "hihi".is_a?String
=>true   # "hihi"是字串嗎?

> 12.class
=> Fixnum
> 1.2.class
=> Float
> "hihi".class
=> String

is_a?::�class這一類會直接回覆給你關於物件本身訊息的方法,稱為反映式方法(Reflection Methods)。

  • 方法(Method)是什麼?

方法就是一些函數指令,也可以當他是個黑箱,你把左邊的東西放進去,搖一搖,然後右邊就會跑出些東西來。每一個方法都會回傳點什麼,就算是沒東西,也會跟你說聲這是nil

有些方法的"副作用"比他回傳的結果要有用的許多,例如:puts,當你在IRB中輸入> puts "hi",這個puts方法會先產生副作用:印出輸入的字串("hi"),最後再回傳=> nil

> puts"hi"
hi
=> nil

當你在寫自己的方法時,假如你忘記考慮回傳的狀態,很有可能會得到奇怪的結果,所以一定要很清楚自己現在寫了什麼程式碼,然後會輸出什麼回傳結果。

方法(Methods)是允許接受傳入值(inputs),在方法右邊的小括號可以被省略,如:> puts("hi")可以寫成> puts"hi",只要你知道自己在寫什麼,把這些省起來是ok的。

> 1+2 == 3意思是 1+2是否會等於3,也就是會不會回傳"true",最明確的寫法是> 1.+(2).==(3)

上面那個例子同時適用於方法鏈接(Method Chaining),就是你串連一堆方法的時候,會先執行左邊的方法,回傳的結果再和右邊的比對,以剛剛的例子> 1+2 == 3來說,先運算左邊的1+2 = 3,然後再比對左右兩邊3 == 3是否為真( true)。這種模式就可以讓你優雅地將數行程式碼串接在一起。

  • Bang Methods(Methods!)

Bang Methods是指"!"結尾的方法,使用之後會直接更改原物件的值,如:sort!。驚嘆號是要提醒你注意:你正在危險的範圍中, 必須小心使用。記住當你在IRB中使用一個普通的方法,會回傳一個結果,並保留原本的物件,但是Bang Methods會覆寫原本的物件,具有不可逆的破壞性。

> my_numbers = [1, 5, 3, 2]
=> [1, 5, 3, 2]
> my_numbers.sort
=> [1, 2, 3, 5]
> my_numbers
=> [1, 5, 3, 2]
# 仍維持原物件的值

> my_numbers.sort!
=> [1, 2, 3, 5]
> my_numbers
=> [1, 2, 3, 5]
# my_numbers已被sort!方法所覆寫

方法若以"?"做結尾,則會回傳 true或 false。那麼,究竟這些個方法是打哪兒來的呢?

答案就是:類別(Classes),類別像是一把保護傘,賦予物件在該類別下所有的通用方法,舉例來說:你(對就是你本人)是Person這個類別的實體,你從Person繼承了許多的行為方法,例如#笑、#走、#說話…等等。

這個在程式中非常有用,因為常常會需要創造某個類別的實體,如果每次都要重複寫同樣的那些方法,感覺就有點蠢。所以將方法寫在類別之中,那麼這個類別下的所有實體就會繼承這些方法。此外類別(�class)本身也可以進行繼承。例如:Person這個類別有許多方法,但其中有些方法是繼承至Mamal類別或者 LivingThing類別,你可以使用任何來自於上一代的方法。

在Ruby中試試看一個有趣的練習:使用::superclass查問類別的上一代是什麼?如果一直往上追問,會發現所有東西都繼承於BasicObjectBasicObject是大多數方法裡的初始物件。

> 1.class.superclass.superclass.superclass.superclass
=> BasicObject
> BasicObject.methods
=> # giant list of methods 一大票方法

::methods方法使用在類別上,會回傳所有的類別方法,而::instance_methods則會回傳該類別實體的所有方法,例如:

"hello".methods = String.instance_methods
"hello"是字串(String)這個類別的實體所以和String.instance_methods相等,不等於下面:
String.methods

object_id可查看物件的id,…有時候可能會出現奇怪的錯誤,例如:你修改了某個物件,但卻沒有變動,這時候你可以試著查看的id,可能就會發現你修改的只是該物件的山寨版。

試著寫下你自己的方法,你可以任意的給輸入值命名,語法像這樣: def methodname(argument1, argument2),(參數)的括號是可以省略的,每個方法絕對會回傳一個return的狀態,或者最後一段程式碼的運行結果。

在IRB中你也可以直接寫方法,他會自動偵測出你是否尚未完成語法指令,例如:只有寫了def開頭,還沒有給一個end的結尾,或者是括號沒有成對。

> def speak(words)
>   puts words
>   return true
> end
=> nil   # ignore this
> speak("hello!")
hello!
=> true

輸入值能不能什麼都沒有是個空值呢?要是方法中需要個輸入值(inputs),但卻什麼都沒有怎麼辦呢?很簡單,只要先指派好預設值,一切就沒問題。

> def speak(words="shhhh")
>   puts words
> end   # implicitly returns what puts returns... nil!
=> nil   # ignore this
> speak   # no input
shhhh
=> nil

======== Ruby Explained是用"In-Plain-Engilish"來介紹Ruby的核心概念,這些概念也常見於其他的介紹中,不過在Erik Trautman這裡是免費而且儘量的淺顯易懂。

Erik Trautman說自己在學習新東西的時候,他希望有人能把他當做五歲小孩,為他進行解釋,Erik認為這樣是最好的學習方法,而且能避免錯失任何東西。 翻譯:Translate from Erik Trautman

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment