Solidity 的繼承
我想以更好的方式實現我的契約,並希望使用繼承。我寫了程式碼,我遇到了一個問題,我想在契約 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
具有inves
和totalInvesCount
(我重命名)的功能。那些對應於public
mapping
andfunction
inA
that 由 繼承B
。另外,請注意
B
部署在 address0xbbf...
。A
根本沒有部署。B
函式和映射也是如此,您可以將它們視為B
.您可以直接部署
A
並與之交談,但它會有不同的地址,因此它有自己的儲存空間。您不會得到相同的值,因為這些合約在各個方面都是分開的,除非它們基於相同的程式碼。如果您繼續執行此操作,則
A
登陸不同的地址。我得到了0x0dc...
。如果我願意,我可以與它交談,但它不會對 產生任何影響,
B
並且B
不會對 產生任何影響A
。您可能希望
A
從 separate 可以訪問 separateB
,因此每個合約都有自己的地址並且它們會進行通信。如果是這種情況,那麼您根本不想要繼承。你想要作曲。繼承和組合看起來非常相似。這就是它的樣子。注意通知
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); } }
如果您真的想要繼承或組合,以下內容可能會幫助您解決問題。
問問自己,這更像是“司機駕駛汽車”還是“掀背車就是汽車”。前者是組合,後者是繼承。前者更緊湊,因為不需要將汽車的所有程式碼匯總到駕駛員中 - 只需了解控制。後者總是累積的,所以隨著更多的程式碼被繼承,合約會變得越來越大。
希望能幫助到你。