Hi there, I’m trying to understand how inheritance works in solidity and the Ownable contract can be a good example. In Contract Test, I defined a new _owner addresss variable which is the same with the one in the parent contract. The function getOwner() returns the _owner in this contract, and the function owner() in Ownable is also callable and returns the value of _owner in the parent contract.
In the second contract, both getOwner() and owner() returns the value of _owner in the parent contract. I am just wondering, why are private variables are still callable through a public function in the parent contract.
In the first contract, the same state variable exist in both parent and child contracts. They are both valid for calling. I’m a bit confused about this part. Is there a naming conflict or a problem of this sort?
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;
import "@openzeppelin/contracts/access/Ownable.sol";
contract Test is Ownable {
address private _owner;
constructor() {
_owner = _msgSender();
}
function getOwner() public view returns(address) {
return _owner;
}
}
contract Test2 is Ownable {
function getOwner() public view returns(address) {
return super.owner();
}
}
To further illustrate the above question, I did another example. The contracts Parent and Child both work fine, however, both store(uint256) and retrieve() are not virtual and have not been override, why are these contracts OK?
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;
contract Storage {
uint256 number;
/**
* @dev Store value in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
}
/**
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
return number;
}
}
contract Parent is Storage{
}
contract Child is Storage, Parent {
}
No, I do not think so, cause the variable _owner in the parent contract only can be access to in parent contract, cause you can find this in the Solidity 0.8.5 documentation:
Private functions and state variables are only visible for the contract they are defined in
and not in derived contracts.
So maybe you can write a another function in the Test, eg:
/// Only for TEST !!!
function setOwner(address newOwner) public {
_owner = newOwner;
}
If you set another account that is different from the deployer address, you will find, getOwner() and owner() will return the different value.
I think cause the variable _owner in the parent contract and in Test contract, they are all the type of address, so for the layout of these variables in storage are one by one, so I think there will not have any conflict, please correct me if I have said anything wrong.
Emmm, I think the contract Parent and Child are derived from the Storage, this means Parent and Child can access to the public, external and internal functions and variables easily, but not for private variable. I hope I make myself clear.
Thanks @Skyge . Your help is very much appreciated.
I guess the Child contract only extends Storage and Parent contracts. It is not duplicating anything, i.e., Storage contract is in its own chunk of storage, and Parent comes along and adds or modifies something to it (in this case, it adds and modifies nothing). Finally Child comes long, and adds and modifies something to it (again, nothing is added or modified). At the end, the storage for the contract Child is pretty much the same with that for Storage. Is this what happened?
Just trying to get to the bottom of things. In this case, the bottom in my mind would be what is being written on storage. (Just realized I could check bytecode for all three contracts. Maybe this is the way.)
Bytecode for three contracts differ for a chunk illustrated in the graph. Not sure what they are, but now I know they are different. The total length is exactly the same though.