在Ruby中所有的東西都是object,意思是說包含class也都是instance,這跟我們在其它語言所學的class似乎不太相同,但這是Ruby的一個特色,也是Ruby能如此有彈性的原因之一。
Open class
Ruby的class是開放式的,因此可以很輕易的在現有的class中任意加入新的method,我們實際來看個例子 :
String
是Ruby的standard class,透過以上方式我們為 String
加上了 say_hello
這個method,在這之後所有的 String
都可以使用 say_hello
,在寫 Rails
時常聽到的 monkey patch
就是透過這種方式來達成。
Classes are objects
所有的class都是 Class
的instance,這句話有點饒舌,我們透過以下例子來瞭解 :
先建立一個叫 User
的class,再透過 User.new
產生出 user
這個instance,從這段code我們可以很清楚的看出 user
的class叫做 User
,而 User
的class是 Class
(這裡並非superclass,所以別跟繼承搞混了) ,這就表示 User
其實也是 Class
的instance,而 Class
則是自已的instance,從這張圖可以看出它們的關係 :
我們都知道Ruby中要new object可以使用 Class.new
,這裡先思考一下為什麼Ruby的方法這麼與眾不同,來看看其它語言是怎麼new object :
var user = new Object(); // javascriptuser = User() # pythonUser user = new User(); // Java
這是因為在Ruby的class method中有 new
的原因,根據ruby-doc的說法 new
會建立一組anonymous class(匿名類別),如果你想當成一般的class則只需要將他指派給一組常數即可。
根據文件的說明,我們再來看到這個例子 :
中間的 new_class
是為了讓我們瞭解anonymous class,省略後就變成
User = Class.new
就是我們常見的class了,也就是說當我們宣告一個class時Ruby會自動為我們建立一組anonymous class並指派給我們所指定的常數。
class User
end
Ruby eigenclass
Ruby中所有的object都存在叫做eigenclass(或稱singleton class)的metaclass,在 new
的時後Ruby會自動為我們產生eigenclass,一般來說我們無法看到eigenclass,但我們可以透過Ruby提供的方法來觀察到eigenclass :
Eigenclass其實是繼承自 Class
的一個subclass,用下圖來視覺化object與eigenclass的關係
也是因為eigenclass的存在幫助我們在Ruby中實現類似於其它語言的static method,接下來看如何去存取eigenclass :
要存取eigenclass共有3種方法,這段code我們為 User
定義了3個class method,為instance定義了一個instance method,這裡要注意到class method與instance method裡的變數並不能互相存取。
上面範例第1種方法的self可以替換成任何你想要存取eigenclass的object,因為self寫在 User
class中,所以這裡的self指的是 User
,當然我們也可以為 user
這個instance定義自已的singleton method(eigenclass method)
Eigenclass method也可以稱為singleton method,但為了區分eigenclass method,一般習慣將class的eigenclass method稱為class method,而instance的eigenclass method稱為singleton method
為instance定義自已的singleton method,代表了這個method只屬於該instance,就算來自相同的class也無法使用它人的singleton method,在此範例中 user
就無法使用 monkey_method
,而 monkey
無法使用 user_method
。
最後
Ruby的class包含許多特性與結構,很多人包含我自已一開始都是直接從rails學起,根本不瞭解Ruby是怎麼一回事,在看別人寫的gem時更是一知半解,當我們實際去瞭解Ruby這個語言時才有辦法寫出更優雅的ruby code。