設計一個類時,往往需要考慮是否將一個方法設為final。可能會覺得使用自己的類時執行效率非常重要,沒有人想覆蓋自己的方法。這種想法在某些時候是正確的。
但要慎重作出自己的假定。通常,我們很難預測一個類以後會以什麼樣的形式再生或重復利用。常規用途的類尤其如此。若將一個方法定義成final,就可能杜絕了在其他程序員的項目中對自己的類進行繼承的途徑,因為我們根本沒有想到它會象那樣使用。
標准Java庫是闡述這一觀點的最好例子。其中特別常用的一個類是Vector。如果我們考慮代碼的執行效率,就會發現只有不把任何方法設為final,才能使其發揮更大的作用。我們很容易就會想到自己應繼承和覆蓋如此有用的一個類,但它的設計者卻否定了我們的想法。但我們至少可以用兩個理由來反駁他們。首先,Stack(堆棧)是從Vector繼承來的,亦即Stack“是”一個Vector,這種說法是不確切的。其次,對於Vector許多重要的方法,如addElement()以及elementAt()等,它們都變成了synchronized(同步的)。正如在第14章要講到的那樣,這會造成顯著的性能開銷,可能會把final提供的性能改善抵銷得一干二淨。因此,程序員不得不猜測到底應該在哪裡進行優化。在標准庫裡居然采用了如此笨拙的設計,真不敢想象會在程序員裡引發什麼樣的情緒。
另一個值得注意的是Hashtable(散列表),它是另一個重要的標准類。該類沒有采用任何final方法。正如我們在本書其他地方提到的那樣,顯然一些類的設計人員與其他設計人員有著全然不同的素質(注意比較Hashtable極短的方法名與Vecor的方法名)。對類庫的用戶來說,這顯然是不應該如此輕易就能看出的。一個產品的設計變得不一致後,會加大用戶的工作量。這也從另一個側面強調了代碼設計與檢查時需要很強的責任心。