The paragraph specifically mentions that only function types are by default internal, and contract functions are by default public, even though I agree the wording is a little bit confusing. It says nowhere that they are at the same time both public and internal.
I think that there is some confusion to what a function type is. The same way you specify the type for a 256 int variable with the keyword uint256, you can also specify the type of a variable that will hold a function. The only difference is that this type declaration is a little more complex since functions are more complex and it looks like this:
function (param types) {internal|external} [pure|constant|view|payable] [returns (return types)] varName;
You can then assign to the variable varName a function that has the same type that you defined. This is only possible inside another function.
As a very simple example:
contract Example{
function(uint256) returns (uint256) varName;
function simpleFunction(uint256 parameter) returns (uint256){
return parameter;
}
function test(){
varName = simpleFunction;
}
}
Where varName is the variable of function type, while simpleFunction and test are normal contract functions
Just so you have a simple definition for all those access classifiers:
- public - all can access
- external - Cannot be accessed internally, only externally
- internal - only this contract and contracts deriving from it can access
- private - can be accessed only from this contract
As you can notice private is a subset of internal and external is a subset of public.
I see good observations about style but I didn't see the safety aspect.
Setting a variable to private ensures that it can only be manipulated via functions in the contract designed for that purpose and never by a successor contract that inherited it.
That means an errant contract could not accidentally zero out, say, owner
... a potentially disastrous accident that is preventable with private
.
So, it's worth considering for vital state elements.
Hope it helps.
UPDATE
pragma solidity 0.4.25;
contract Risky {
string public vital;
constructor() public {
vital = "do not change";
}
}
contract Careless is Risky {
function oops() public {
/*
Since vital is "public", this child contract is free to write to it.
This is not ideal because it could lead to critical values overwritten.
This child contract is free to make mistakes that could be disasterous.
*/
vital = "game over";
}
}
/*
----------------------------------------
Using private for safety
----------------------------------------
*/
contract Cautious {
string private vital;
constructor() public {
vital = "cannot be changed by accident";
}
function getVital() public view returns(string) {
return vital;
}
function setVital(string youKnowWhatYoureDoing) public {
vital = youKnowWhatYoureDoing;
}
}
contract Isolated is Cautious {
/*
This child cannot stomp on Cautious' "vital" even if it wants to because it's not "public" or "internal".
It *must* use Cautious' getter and setter functions which means Cautious is in control.
*/
}
Best Answer
See https://programtheblockchain.com/posts/2018/01/02/making-smart-contracts-with-public-variables/ for a full explanation.
Yes, the default visibility for state variables is
internal
(as per v0.8.4). Marking itpublic
makes it easy to read the variable in a DApp or from another smart contract.