沒有實現的介面或函式有什麼用?
以這段程式碼為例。該介面包含沒有實現的功能,所以它是如何有用的。
pragma solidity ^0.5.0; interface Calculator { function getResult() external view returns(uint); } contract Test is Calculator { constructor() public {} function getResult() external view returns(uint){ uint a = 1; uint b = 2; uint result = a + b; return result; } }
此程式碼的工作方式與第一個程式碼有何不同?使用沒有實現的介面或函式有什麼好處?
pragma solidity ^0.5.0; contract Test { constructor() public {} function getResult() external view returns(uint){ uint a = 1; uint b = 2; uint result = a + b; return result; } }
- 在呼叫合約中節省字節碼大小。
- 建立標準並確保合規。
- 檢測開發人員的錯誤和疏忽。
節約
考慮將與 Test 互動的合約客戶端。可以在客戶端創建一個 Test 實例,如下所示:
contract Client { Test t; constructor(address test) public { t = Test(test); } }
這會起作用,但問題是客戶端的字節碼大小將是測試大小加上客戶端大小,因為編譯器會將完整的測試實現匯總到客戶端中。客戶端不需要所有這些程式碼。它只需要它要呼叫的函式的介面。
如果改用介面契約(在您的範例中為計算器,或者像 ITest 這樣的命名,這是事實上的命名標準),它可以用更小的字節碼實現相同的結果。
contract Client { Calculator c; constructor(address calculator) public { c = Calculator(calculator); } }
順便說一句,您可以將輸入(仍然是地址)轉換為合約類型:
constructor(Calculator calculator) public { c = calculator; }
甜的。
標準
許多標準被定義為功能介面和精確行為規範。例如,ERC20 是一個介面,但沒有特定的實現,只要功能以某種方式工作 - 可以通過測試套件確認。通常會看到類似的內容:
contract MyToken is IERC20 { ...
其中 IERC20 是 ERC20 合約的定義介面。
如果 MyToken 是可部署的,那麼這就確定了 IERC20 介面所需的每個函式都有一個實現(不是未定義的)。這與…有關
開發人員錯誤
在開發階段,不一致可能會蔓延到復雜的系統中。審稿人發現不一致也可能在認知上很繁重。介面可以用作一種錯誤檢測。
假設有人決定
getResult()
需要一個論點,例如getResult(address user) ...
。這是一個重要的設計更改,會影響很多事情。因為contract Test is Calculator {
除非更新介面,否則不會部署測試。為什麼/如何?
函式簽名是函式名稱和參數散列的前 4 個字節,因此
getResult()
在getResult(uint)
字節碼級別是完全不同的函式。實際上,這意味著 Test 將編譯,但不會部署,因為它不會定義繼承介面中定義的強制函式之一。這正是我們想要的,因為要麼 a) 介面已重新定義,這意味著所有客戶端都需要調整,要麼 b) 實現不正確,這意味著添加該參數是不可接受的,或者 c) 缺少實現並且提供的是除了強制性功能,但不是替代品(兩者都需要)。
為了樣式和一致性,在 1:1 的基礎上為實現定義介面可能是一個好習慣。
希望能幫助到你。