Solidity

Solidity 的繼承

  • January 2, 2019

我想以更好的方式實現我的契約,並希望使用繼承。我寫了程式碼,我遇到了一個問題,我想在契約 B 中訪問契約 A 的映射變數。我的程式碼如下

pragma solidity ^0.5;
import "./ConvertLib.sol";

contract A {
   mapping(address => address[]) public inves;

   function totalInves() public view returns(uint) {
       return(inves[msg.sender].length);
   }

}

另一份契約是

pragma solidity ^0.5;
import "./ConvertLib.sol";
import "./A.sol";

contract B is A {
   function total() public view returns(uint) {
       return(inves[msg.sender].length);
   }
}

合約 A 也有更多的功能,它將數據儲存在映射函式中。我正在使用 Truffle 框架,所以我試圖做的是呼叫這兩個函式。當我使用 truffle 在契約 A 中呼叫函式 totalInves 時,它給了我這個(Truffle 控制台),我正在執行 testrpc

truffle(development)> var acont = await A.deployed()
truffle(development)> var data = acont.totalInves.call({from:acc[0]})
undefined
truffle(development)> data
<BN: 1>

當我執行合約 B 函式時,它給了我這個

truffle(development)> var bcont = await B.deployed()
truffle(development)> var data = bcont.total.call({from:acc[0]})
undefined
truffle(development)> data
<BN: 0>

我很困惑為什麼同一個變數會產生不同的結果,因為如果我呼叫合約 B 中的總函式,它應該給出相同的結果集。

我想你可能誤解了繼承。

B is A,則A原始碼被匯總到B. 這是一個文件:

pragma solidity ^0.5;

contract A  {

     mapping(address =>address[]) public inves;

     function totalInvesCount(address index) public view returns(uint){
       return(inves[index].length);
     }

}

// import "./A.sol"; // You use this if A.sol is a separate file

contract B is A {

}

中發生的事情不多B。在 Remix中B顯示正在發生的事情。

在此處輸入圖像描述

請注意,它B具有investotalInvesCount(我重命名)的功能。那些對應於public mappingand functionin Athat 由 繼承B

另外,請注意B部署在 address 0xbbf...A根本沒有部署。B函式和映射也是如此,您可以將它們視為B.

您可以直接部署A並與之交談,但它會有不同的地址,因此它有自己的儲存空間。您不會得到相同的值,因為這些合約在各個方面都是分開的,除非它們基於相同的程式碼。

如果您繼續執行此操作,則A登陸不同的地址。我得到了0x0dc...

在此處輸入圖像描述

如果我願意,我可以與它交談,但它不會對 產生任何影響,B並且B不會對 產生任何影響A

您可能希望A從 separate 可以訪問 separate B,因此每個合約都有自己的地址並且它們會進行通信。如果是這種情況,那麼您根本不想要繼承。你想要作曲。

繼承和組合看起來非常相似。這就是它的樣子。注意通知B位置的額外問題A。另請注意,我們刪除了繼承部分。B不是A因為我們沒有使用繼承。

pragma solidity ^0.5;

contract A  {

     mapping(address =>address[]) public inves;

     function totalInvesCount(address index) public view returns(uint){
       return(inves[index].length);
     }

}

// import "./A.sol"; // You use this if A.sol is a separate file

contract B {

   A a;

   constructor(address _a) public {
       a = A(_a); 
   }

   function totalInvesCount() public view returns(uint) {
       return a.totalInvesCount(msg.sender);
   }

}

如果您真的想要繼承或組合,以下內容可能會幫助您解決問題。

問問自己,這更像是“司機駕駛汽車”還是“掀背車就是汽車”。前者是組合,後者是繼承。前者更緊湊,因為不需要將汽車的所有程式碼匯總到駕駛員中 - 只需了解控制。後者總是累積的,所以隨著更多的程式碼被繼承,合約會變得越來越大。

希望能幫助到你。

引用自:https://ethereum.stackexchange.com/questions/64736