2007年06月30日

程式語言中的介面,在個體之間協議互動行為的多種形式

Tags: interface class method 動態語言

racklin 說: 我的重點還是只放在 "關注類別是否有實作方法" 也就是 "介面" 的這個概念, 因為原文是討論這個議題. 嗯,我大概是跳太快了。我清楚 interface 是什麼。所以我的回應是在說明「個體之間如何協議互動行為」亦即「軟體合約」的形式。

以C/C++為例,在早期,程序員學了 C++ 可是還是要寫 C 程式的時代,我們會自己用 C 語言實作類別繼承、動態連結等觀念。但我們用的是 C compiler 而非 C++ compiler ,所以很多事我們必須自己處理。其中一點就是個體行為的協議。方法一、在函數文件上說明傳入的個體需擁有哪些行為,我在函數中會檢查此個體是否擁有此行為(函數指標是否為給定了)。方法二、限定一個 struct (只有純函數指標宣告),呼叫者要自己填一張函數指標表傳入,這其實就是 interface 的概念。


例如下列的程式碼,就是用 struct 宣告一張個體行為介面表。完整程式碼可見於 bbslib-20010331

使用方式通常如下列所示。宣告一個 buffer struct ,定義需要的函數。建構函數中要配置並指派函數指標。注意,這是 C ,不是 C++ 。一切要自己來。用 Java 的用語說明,此 buffer 類別的用途,在於將 primitive type 的字串轉成 object 。亦即 buffer 是一個 Wrapper Class 。最後在 main 和 print_content_and_length 中展示了近似 C++ 的敘述。

在當時,因為我們總是用強迫轉型的方式傳遞個體,所以 struct 中的宣告,僅是告知程序員應有什麼,對 compiler 是沒用的。程序員要自己掌握型態,軟體合約在程序員腦中、口中與文件中。

當然,C++/Java compiler 就不用那麼麻煩了。它會幫我們處理這些小事。它們會幫我們維護那張表,而 interface 的宣告內容就成為函數的說明文件之一。若以虛擬碼巨集表示:

上述動作隱含於 C++/Java 的 compile 動作中,而在動態語言中往往是明顯地呈現在程式碼中。這並無不妥,因為動態語言往往具有中介語言/巨集語言的泛型表達能力。

對於錯誤捕捉之事。靜態語言仰賴各種宣告資訊,提供 compiler 在編譯時期核對。但我因為以往有 C 語言實作的經驗,所以向來不太倚重 interface 防錯能力。

另一方面,動態語言沒有編譯時期,它們在執行時期才能確定個體資訊,故必須仰賴更動態的處理策略。現行最有效的策略就是玩真的,提供 test case 供 tester 在執行時期測試。

嗯。我這幾天就一直在想,為什麼我在寫動態語言程式時,不像寫 C/C++ 那麼強調型態宣告,卻不覺得程式會出錯?後來想到了,那是因為有 TDD。而且 tester 所產生的結果更可靠。


Posted by shirock at 樂多Roodo! │12:00 │回應(0)引用(2)C/C++
樂多分類:學術/學習 工具:編輯本文
Ads by Roodo! 

引用URL

http://cgi.blog.roodo.com/trackback/3556355
引用列表:
這幾天抽空檢視了一下那些舊程式碼,才發現不是程式碼的問題,而是我用錯編譯器了
舊程式碼中的 void* 轉型【石頭閒語】 at 2007年07月11日 18:11
從泛型與編譯器的關係來看,沒有編譯器的動態語言環境不需要像 template 這類的泛型功能
C 和動態語言的泛型【石頭閒語】 at 2007年07月19日 18:14