最近更新: 2009-12-07

以PHP觀點來看 C++ template

從 C++ Template 到 Java Generic,一步一步來一文,我用 Java 的泛型語法改寫了一個 C++ 樣板類別。 我也用 PHP、JavaScript 和 Ruby 來做同樣的事,看看這些動態語言有沒有泛型處理能力。

我要用 PHP 改寫的 C++ 樣板類別,其源碼同從 C++ Template 到 Java Generic,一步一步來。本文不再重複,直接說明 PHP 的改寫過程。

PHP 改寫過程

PHP 的類別定義語法和 C++/Java 差異不大(其實是像Java)。 Cx 是個樣板類別,定義中使用的型別為參數化、可替換者。 在 PHP 中的意義,就代表著不具體的型別,通常就是用 var 或不寫。 PHP 的變數都是用 $ 開頭,存取資料成員時一定要用 $this 指示,不可省略。 方法定義要加關鍵字 function ,略去參數與回傳值的型別。 PHP 的建構子有兩種寫法:

  1. 舊式(PHP4)跟 C++/Java 一樣,跟類別同名的方法即為建構子。
  2. 新式(PHP5)則統一名稱為 __construct

本例兩種都用。

Cx 有兩個建構子,一個是無參數的預設建構子,另一個是一個參數的建構子。PHP 可以用參數預設值的方式簡化建構子的改寫動作,寫成一個。其實 C++ 就可以用參數預設值的方式將兩個建構子寫成一個建構子。 只是因為 Java, JavaScript 不支援參數預設值,所以我的 C++ 程式碼才特意分開來寫。

class Cx {
    private $data;

    public function Cx($v) { //舊式建構子寫法。剛好跟 C++ 一樣,不用改。

          $this->data = $v;
    }

    public function getData() {
        return $this->data->value();
    }
};

class N {
    private $n;

    //新式建構子寫法,名稱一律用 __construct

    //用參數預設值的方式簡化建構子的改寫動作

    public function __construct($v = 0) { $this->n = $v; }

    public function value() {
        return -$this->n;
    }
};

class M {
    private $m;

    public function __construct($v = 0) { $this->m = $v; }

    public function value() {
        return $this->m * 10;
    }
};

class S {
    private $s;

    public function __construct($v = "") { $this->s = $v; }

    public function value() {
        return $this->s;
    }
};

緊接著上面的內容,接著的要改寫 C++ 的 main() 。在 PHP 中不需要指示程序進入點,直接寫即可。

PHP 的變數不用宣告型別,由右值的實體決定左值的型別。 C# 3.0 引入了類似觀念。但是 PHP 的變數可以再次指派其他型別的資料給左值;C# 3.0 則在第一次指派後便固定型別,之後不可指派其他型別的內容給變數。

$n = new N(1);

//不需要特別的樣板語法。

$cn = new Cx( $n );

echo $cn->getData(), "\n";

$m = new M(1);
$cm = new Cx( $m );
echo $cm->getData(), "\n";

$s = new S("hello");
$cs = new Cx( $s );
echo $cs->getData(), "\n";

在 C++ 中的樣板類別 Cx ,到了 PHP 之後,跟一般的類別沒兩樣。雖然 PHP 的語法很像 C++, Java ,但至少它還算是動態語言,故其語義基本上仍是泛型的。

有些沒接觸過動態語言的人,對於泛型有一種奇怪的誤解,他們認為動態語言並沒有泛型語法,所以動態語言沒有泛型能力。我在C++和動態語言的泛型一文中曾經駁斥過這一論點。從語意看,動態語言其實就是泛型的。

移除 C++ 型別資訊,以 PHP 語法改寫的 N, M, S 類別定義,也僅僅只剩兩行程式碼不同,這意味著我們可以進一步重構彙整。 而 PHP5 的新式建構子寫法此時也看得出一個好處,就是名稱統一,重構類別時不必再去修改建構子的名稱。

相關文章
樂多舊網址: http://blog.roodo.com/rocksaying/archives/10934759.html