Ruby的Class與Eigenclass

Zneu Ray
5 min readFeb 12, 2017

--

在Ruby中所有的東西都是object,意思是說包含class也都是instance,這跟我們在其它語言所學的class似乎不太相同,但這是Ruby的一個特色,也是Ruby能如此有彈性的原因之一。

Open class

Ruby的class是開放式的,因此可以很輕易的在現有的class中任意加入新的method,我們實際來看個例子 :

open class

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。

--

--