Table of Contents
Understanding visibility specifiers in Solidity
In Solidity, visibility specifiers are crucial for controlling access to functions and variables within smart contracts. They determine who can access these elements and from where.
1. Public visibility
- Public functions or variables can be accessed from outside the contract as well as from within.
- These are commonly used for functions that need to be accessible externally, such as entry points to the contract.
2. Private visibility
- Private functions or variables are only accessible from within the contract that defines them.
- They cannot be accessed from outside the contract or from derived contracts.
3. Internal visibility
- Internal functions or variables are accessible from within the contract as well as from derived contracts.
- They cannot be accessed externally, i.e., outside the contract hierarchy.
🔥 Check this course out: Build Hogwarts Sorting Hat dApp on Polygon
The difference between internal and private
To understand the difference between internal and private specifiers, let’s consider a metaphor of a house and its rooms:
1. Private: The room locked inside
- When a function or variable is marked as private, it’s like a room in your house that has a lock on the door.
- Only you, the owner of the house (or the contract), can access this room. It’s entirely hidden from the outside world.
- Even if your friends (or derived contracts) are visiting your house, they can’t enter this room because it’s locked and exclusive to you.
2. Internal: The family room
- Internal functions or variables, on the other hand, are like the family room in your house.
- This room is accessible to all members of your family (or derived contracts). They can freely enter and use the facilities inside.
- However, outsiders (external contracts) cannot access this room. It’s limited to the family (or derived contracts) only.
Private visibility specifier example
Here’s the coding example for the private visibility specifier.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract House {
uint internal myInternalNumber = 20;
function getInternalNumber() public view returns(uint) {
return myInternalNumber;
}
}
contract MyDerivedHouse is House {
function getInternalNumberFromDerived() public view returns(uint) {
// Can access the internal variable from the parent contract
return myInternalNumber;
}
}
Explanation
- In this example,
myInternalNumber
is declared as internal in theHouse
contract. - The
getInternalNumber()
function allows external access to retrieve the value ofmyInternalNumber
. MyDerivedHouse
is a contract that inherits fromHouse
.- The
getInternalNumberFromDerived()
function demonstrates how the internal variable from the parent contract can be accessed within the derived contract.
🔥 Check this course out: Build a One Piece Personality dApp With Solidity
Internal visibility specifier example
Here’s the coding example for the internal visibility specifier.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract House {
uint private myPrivateNumber = 10;
function getPrivateNumber() public view returns(uint) {
return myPrivateNumber;
}
}
contract ExternalContract {
House private houseInstance;
constructor(address _houseAddress) {
houseInstance = House(_houseAddress);
}
function tryAccessPrivate() public view returns(uint) {
// Cannot access the private variable directly
// Results in a compilation error
// return houseInstance.myPrivateNumber;
// Accessing via public getter function
return houseInstance.getPrivateNumber();
}
}
Explanation
- Here,
myPrivateNumber
is declared as private in theHouse
contract, making it inaccessible from outside the contract. - The
getPrivateNumber()
function provides a way to access the private variable’s value externally. ExternalContract
demonstrates an attempt to directly access the private variable, which results in a compilation error.- Accessing the private variable indirectly through the public getter function (
getPrivateNumber()
) is the proper way to retrieve its value.
Combined example
Let’s illustrate these concepts with Solidity code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract House {
uint private myPrivateNumber = 10;
uint internal myInternalNumber = 20;
function getPrivateNumber() public view returns(uint) {
return myPrivateNumber;
}
function getInternalNumber() public view returns(uint) {
return myInternalNumber;
}
}
contract MyDerivedHouse is House {
function getNumbers() public view returns(uint) {
// Can access internal variable only from the parent contract
// as it's derived from it.
return (myInternalNumber);
}
}
In this example:
myPrivateNumber
is private to theHouse
contract. It cannot be accessed directly fromMyDerivedHouse
.myInternalNumber
is accessible within theHouse
contract and its derived contracts, such asMyDerivedHouse
.
🔥 Check this course out: Create Your Own Ethereum Token in Just 30 Mins
Conclusion
In summary, while both internal and private specifiers restrict access to variables and functions in Solidity, they differ in their scope of accessibility. Private restricts access solely to the defining contract, akin to a locked room, while internal extends that access to derived contracts, resembling a family room open to all family members. Understanding these nuances is crucial for designing secure and efficient smart contracts.
Try it out, ask us questions, and tell us how it went by tagging Metaschool on Social Media.
Follow us on –
🔮Twitter – https://twitter.com/0xmetaschool
🔗LinkedIn – https://www.linkedin.com/company/0xmetaschool/