Visibilidade em Solidity
Neste guia, você vai entender os 4 modificadores de visibilidade mais usados em funções e variáveis:
- public
- private
- internal
- external
Eles controlam quem pode acessar uma função/variável e de onde.
Resumo rápido
| Visibilidade | Mesmo contrato | Contratos filhos | Outros contratos | Chamadas externas |
|---|---|---|---|---|
public |
Sim | Sim | Sim | Sim |
private |
Sim | Não | Não | Não |
internal |
Sim | Sim | Não (direto) | Não |
external |
Não (direto) | Não (direto) | Sim | Sim |
public
Acesso mais aberto. Pode ser chamado:
- dentro do próprio contrato
- por contratos filhos
- por outros contratos
- por carteiras/front-end
Exemplo
uint256 public total;
function incrementar() public {
total += 1;
}
Observação: variável public ganha automaticamente uma função getter.
private
Acesso mais restrito. Só o contrato atual enxerga.
- não pode ser acessado por contratos filhos
- não pode ser acessado por fora
Exemplo
uint256 private segredo;
function definirSegredo(uint256 valor) public {
segredo = valor;
}
Importante: private esconde no nível da linguagem, mas os dados da blockchain ainda podem ser inspecionados por ferramentas de leitura de estado.
internal
Intermediário entre public e private.
- contrato atual: sim
- contratos filhos (herança): sim
- contratos externos sem herança: não direto
Exemplo
function _calcularTaxa(uint256 valor) internal pure returns (uint256) {
return (valor * 2) / 100;
}
Padrão comum: funções auxiliares com prefixo _ como internal.
external
Pensado para ser chamado de fora do contrato.
- pode ser chamado por front-end, carteira e outros contratos
- não pode ser chamado internamente de forma direta (
minhaFuncao()) - se precisar chamar de dentro, use
this.minhaFuncao()(chamada externa, mais cara)
Exemplo
function votar(string calldata candidato) external {
// lógica de voto
}
Dica: em parâmetros dinâmicos (string, bytes, arrays), external + calldata costuma ser mais eficiente que public + memory.
Quando usar cada um
- Use
publicpara funções comuns e simples. - Use
privatepara detalhes internos que não devem ser reutilizados por herança. - Use
internalpara lógica que deve ser reaproveitada por contratos filhos. - Use
externalpara funções focadas em chamadas de fora e melhor eficiência comcalldata.
Dúvidas frequentes
"private deixa meus dados secretos?"
Não. private restringe acesso no código Solidity, mas dados on-chain podem ser lidos por ferramentas de exploração de estado.
"Posso chamar external de dentro do contrato?"
Diretamente (minhaFuncao()) não. Para isso, teria que usar this.minhaFuncao(), que vira chamada externa e custa mais gas.
"Quando escolher public vs external?"
- prefira
publicquando também precisa chamar internamente - prefira
externalpara funções usadas de fora, especialmente com parâmetros dinâmicos
Exemplo completo
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ExemploVisibilidade {
uint256 public contador;
uint256 private segredo;
function incrementar() public {
contador += 1;
}
function setSegredo(uint256 valor) public {
segredo = valor;
}
function _dobro(uint256 x) internal pure returns (uint256) {
return x * 2;
}
function calcularDobroExterno(uint256 x) external pure returns (uint256) {
return x * 2;
}
}