第1章 元這個字眼
元程式設計是編寫能寫代碼的代碼
1.1 鬼城與自由市場
語言構件(language construct)包含各種成員(變量、類、方法等)。
以C++為例,一旦編譯器完成了工作,變量和函數這樣的東西就變得看不見摸不着了,它們隻存在于記憶體中。你沒有辦法向一個類詢問它的執行個體方法,因為當你問出這個問題時,它可能已經消失了。對于C++這樣的語言來說,運作時(runtime)是一個可怕的寂靜之地----鬼城。
而在另外一些語言(如Ruby)中,運作時更像是一個繁忙的自由市場。大多數語言構件依然存在,而且正四處忙碌着。你甚至可以抓住一個構件,詢問它關于它自身的問題。這種方式稱作内省(introspection)
讓我們通過一個執行個體來看看内省究竟是什麼。
class Greeting
def initialize(text)
@text = text
end
def welcome
@text
end
end
複制
my_object = Greeting.new("Hello")
這裡定義了一個Greeting類,并建立了一個Greeting對象。現在我們可以抓住這個對象,并像它提問:
my_object.class #=> Greeting
我問它所屬的類,它十分肯定的回答我:“我是一個Greeting”,現在我要問它有哪些執行個體方法:
my_object.class.instance_methods(false) #=> [:welcome]
我得到的回答是一個數組,其中隻有一個方法welcome。參數false代表我是問它自己的方法,不要它繼承來的方法。接着,我問它有哪些執行個體變量:
my_object.instance_variables #=> [:@text]
它如實回答了我的問題。類和對象都是Ruby世界的一等公民,你可以問出很多資訊來。

ruby
Ruby除了可以在運作時詢問語言構件,還能在運作時建立它們。在程式運作時,能否在welcome方法之外再添加一個執行個體方法?你可能不太了解,究竟什麼情況下會有這樣的需求呢?請看下面的故事。
1.2 程式員Bob的故事
Bob有一個計劃:為電影迷建造一個世界最大的網際網路社交系統。為了實作這個目标,他先要建立一個存放電影名和影評的資料庫。Bob希望借此機會練習編寫可重用的代碼,是以他決定建立一個簡單的代碼庫,用于在資料庫中實作對象的持久化。
1.2.1 Bob的第一次嘗試
Bob編寫了一個代碼庫,把資料庫中的每個表映射到一個類中,同時把每條記錄映射到一個對象中。每當創一個對象或通路它的屬性時,這個對象會産生一條SQL語句并發送給資料庫。所有這些功能都封裝在一個類中。
class Entity
attr_reader :table, :ident
def initialize(table, ident)
@table = table
@ident = ident
Database.sql "INSERT INTO #{@table} (id) VALUES (#{@ident})"
end
def set(col, val)
Database.sql "UPDATE #{@table} SET #{col}='#{val}' WHERE id=#{@ident}"
end
def get(col)
Database.sql ("SELECT #{col} FROM #{@table} WHERE id=#{@ident}")[0][0]
end
end
複制
在Bob的資料庫中,每個表都有一個id字段。每個Entity會儲存這個字段的内容以及它引用的表名。每建立一個Entity對象後,該對象會把自己儲存在資料庫裡。Entity#set方法建立SQL語句更新字段值,而Entity#get方法建立SQL語句讀取字段值。(Bob的Database類用二維數組作為傳回的資料集)
Bob可以繼承Entity類來映射一個指定的表。例如,用Movie類映射一個名為movies的表:
class Movie < Entity
def initialize(ident)
super "movies", ident
end
def title
get "title"
end
def title=(value)
set "title", value
end
def director
get "director"
end
def director=(value)
set "director", value
end
end
複制
Movie類的每個屬性有兩個方法:一個讀方法和一個寫方法。Bob隻要在Ruby指令行解釋器中輸入如下指令,就能把一部電影加載到資料庫裡:
movie = Movie.new(1)
movie.title = "Doctor Strangelove"
movie.director = "Stanley Kubrick"
複制
Bill看了Bob的代碼後說:“重複的代碼太多了。資料庫裡有title字段,代碼裡有@title成員,還有title方法、title=方法、title字元串常量。如果你會元程式設計,用很少的代碼就可以解決這個問題。”
1.2.2 進入元程式設計的世界
==未完待續==