天天看點

solidity.is繼承合約問題

父合約如果允許子合約繼承并修改合約方法的話,可以加上 virtual 關鍵字

子合約重寫父合約的方法的話,需要加上override關鍵字

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

abstract contract context{

function _msgSender() internal view virtual returns (address){
return msg.sender;
}

function _masData() internal view virtual returns (bytes calldata){
return msg.data;
}

}


contract Ownable is context{
    address payable public owner;
    mapping(address => uint) public shares;
    constructor(){
        _transOwner(_msgSender());
    }
    modifier onlyOwner{
        require(owner == _msgSender(),"not the owner");
        _;

    }
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    function _transOwner(address newOwner) internal virtual{
    address oldOwner = owner;
    owner = payable(newOwner);
    emit OwnershipTransferred(oldOwner,owner);
    }

    function  transOwner(address newOwner) public virtual onlyOwner{
        require (newOwner!=address(0),"new address is zero");
        _transOwner(newOwner);

    }

    function reannounceOwner() public virtual onlyOwner{
    _transOwner(address(0));
    }

    function Owner() public view virtual returns (address) {
        return owner;
    }

    function withdraw(uint _amount) onlyOwner public{ 
     //   require(shares[msg.sender] >= _amount,"not enough balance");
        shares[msg.sender] -= _amount;
        payable(msg.sender).transfer(_amount);
    }

    function exposit(uint amount) public{
    shares[msg.sender]=amount;
    }

    function getBalance() public returns(uint bal) {
     bal =shares[msg.sender];
     return bal;
    }
}

contract OwnablePending is Ownable{
    event OwnerTranferred(address indexed oldaddress, address indexed newaddress);
    address private dependingOwner;

function transOwner (address newOwner) public virtual onlyOwner override{
    dependingOwner=newOwner;
    emit OwnerTranferred(Owner(),dependingOwner);

}

function _transOwner(address newOwner) internal virtual override{ 
delete dependingOwner;
super._transOwner(newOwner); //調用繼承的最近的合約内部的方法
}

function accept()public virtual{
    address sender = _msgSender();
    require(sender == dependingOwner);
    _transOwner(sender);
}
}
           

合約的繼承需要按照順序執行

A,

B<-A

C<-A,B,B 可以重寫A,如果順序颠倒的話,就會編譯錯誤

如果某一個函數在多個繼承的合約裡都存在,在子合約裡必須重寫,不然會報錯。

重寫在多個父合約中都重名的函數時,override關鍵字後面要加上所有父合約名字,例如override( B,A)。

在有向環圖的繼承關系中,鑽石繼承(菱形繼承)指一個派生類同時有兩個或兩個以上的基類。

在多重+菱形繼承鍊條上使用super關鍵字時,需要注意的是使用super會調用繼承鍊條上的每一個合約的相關函數,而不是隻調用最近的父合約。

A,

B<-A

C<-A

D<-B,C ,此時 D調用super.func(),則不是執行最近的繼父合約方法,而是按照有向環圖的方式依次向上調用,但是根合約隻會調用一次。

繼續閱讀