智能合約開發

抽象合約

抽象合約是一個只蓋了一半的合約——一個帶有若干空白、留給子合約填補的範本。由於至少有一項行為未被指定,你無法單獨部署它;它的存在是為了被繼承與補完。

合約成為抽象的方式有二:它宣告了至少一個沒有實作的函數(只有以分號結尾的簽章),或它被明確標上 abstract 關鍵字。任何未實作的函數都必須標記 virtual,好讓子代覆寫。與介面的關鍵差異在於:抽象合約可以攜帶真正的狀態變數、建構子、修飾子,以及完整實作的函數——所以當你想共用具體邏輯、同時又強制每個子類別提供少數特定片段時,它就是對的工具。這正是範本方法模式:基底定義整體流程,留下命名的空洞。

繼承抽象基底的合約本身仍是抽象的,直到它實作每一個繼承來的未實作函數(各自帶 override)為止。唯有當再無空白時,它才成為具體且可部署。刻意把一個合約標記為 abstract,即使它已完整實作,也是一種明確的宣告:「這只該作為基底,永不直接部署。」

abstract contract Base {
  function fee() public view virtual returns (uint256); // no body
  function net(uint256 x) public view returns (uint256) {
    return x - fee();   // relies on the child's fee()
  }
}

現在共用邏輯,稍後強制補上空白。

介面與抽象合約之別:介面不能持有狀態,也不能有實作的函數;抽象合約兩者皆可,因此當你需要共用邏輯加上幾個強制空白時,就用它。