Ruby class 基本的覆寫(override)及繼承(inheritance)


首先考考大家,以下寫法,如果呼叫Greeting.hello出現的是哪一個結果呢?

class Greeting
  def self.hello
    "hello"
  end

  def self.hello
    "say hi"
  end
end

不知道各位猜對了嗎?比較晚出現的code,會將較早出現的code覆寫掉,所以答案是出現"say hi"

1. 覆寫

最近嘗試寫一些Ruby gem,才發現這些關於class很驚人的事情,從以上例子進行延伸,其實我們可以對Ruby當中既存的class和method進行任意的修改及延伸。這有什麼好處呢?主要是在設定不同class時,可以非常簡便的互相取用資源,也可以從既有的class取得內容、進行編修。

假設我們需要針對所有字串(String)增加一個method,可以直接呼叫String出來修改:

class String
  def hello
    "Hello #{self}"
  end
end

"John".hello
# => "Hello John"

"Pan".hello
# => "Hello Pan"

這個觀念最厲害的地方在於不管我們使用什麼字串,由於都是屬於String這個class底下的物件,所以設定的method都可以套用上去。假如我們對既有的method不滿,也可以用這個方式來增補,例如我們希望將字串的downcasereverse這兩個method合併為一個downswap,那可以用以下寫法:

class String
  def downswap
    self.downcase.reverse
  end
end

"APPLE".downswap
# => elppa

這樣設定好以後,就可以在字串上使用。

2. 繼承

另外,class也有繼承的概念,就像我們在Rails的controller當中,會看到ApplicationController < ActionController的寫法,意思是所有在ActionController當中能夠使用的功能,都會繼承到ApplicationController裡面,也因此我們才有很方便的callbacks可以使用,例如before_filter等等。

我們也可以在自訂的class當中使用繼承的觀念:

class Feature
  attr_accessor :feature
  def initialize(feature="safe")
    @feature = feature
  end
end

class Product < Feature
  def price
    "$ 500"
  end
end

feature = Feature.new
feature.feature
# => "safe"

product = Product.new
product.feature
# => "safe"

從上面的例子可以看出,我們在Product這個class中雖然什麼都沒有寫,但因為已經開宗明義寫出是從Feature這個class繼承而來,所以所有變數、method都可以直接取用,算是非常方便的一個地方。另外還多了一個price method可以取用,會顯示跟幫助國民黨一樣可以拿到的500元。

這兩個觀念對於class的編修非常基本,但對於了解整個Ruby和Rails的脈絡是非常有用,尤其是目標要自行撰寫gem或framework的朋友來說是非知道不可啊~

延伸閱讀

Ruby Inheritance

Ruby Delegation