Design de software

Encapsulamento em OOP: entendendo o controle de acesso do Swift

Ao estudar OOP, você ouve “encapsulamento” centenas de vezes, mas quando alguém pergunta “Então, como fazer isso no código?”, é comum ficar sem palavras. Você entende o conceito, mas não sabe por onde começar a escrever.

5 min de leitura
Imagem de capa de Encapsulamento em OOP: entendendo o controle de acesso do Swift

Ao estudar OOP, você ouve “encapsulamento” centenas de vezes, mas quando alguém pergunta “Então, como fazer isso no código?”, é comum ficar sem palavras. Você entende o conceito, mas não sabe por onde começar a escrever.

Em resumo, encapsulamento é esconder os dados internos de um objeto para impedir alterações arbitrárias externas e permitir acesso apenas por caminhos definidos. No Swift, isso é implementado com modificadores de acesso.

Hoje veremos em código real os cinco níveis de controle de acesso, incluindo private e internal, e entenderemos como o ocultamento de informações protege o código.

O que exatamente é encapsulamento?

Encapsulamento (Encapsulation) é uma das quatro características fundamentais de OOP.

Em uma frase:

Agrupar os dados e as funções que os manipulam, ocultar o interior e expor apenas o necessário.

Por que ocultar?

Pense em uma conta bancária. Seria um desastre se qualquer pessoa pudesse alterar diretamente o saldo para qualquer número.

Depósitos e saques precisam seguir procedimentos definidos, garantindo regras como “não é possível sacar mais do que o saldo”.

Impedir o acesso direto aos valores internos e abrir apenas caminhos validados é chamado de ocultamento de informações.

Se encapsulamento é o conceito mais amplo, ocultamento de informações é o princípio central que o torna possível.


Comparação rápida dos cinco níveis de acesso do Swift

O Swift divide o escopo de acesso em cinco níveis, organizados aqui do mais restrito ao mais amplo.

(Com base na sintaxe mais recente do Swift em 2026.)

Modificador de acesso Escopo acessível Uso principal
private Dentro do bloco de chaves da declaração Estado interno que você realmente quer ocultar
fileprivate Todo o mesmo arquivo-fonte Tipos colaboradores no mesmo arquivo
internal Todo o mesmo módulo (app/framework) Valor padrão; a maior parte do código
public Também pode ser usado de outros módulos API pública fora da biblioteca
open Permite herança e sobrescrita a partir de outros módulos Pontos de extensão de framework

Há um ponto importante para lembrar.

Se você não adicionar nada, internal será o padrão.

Por isso o código funcionava normalmente dentro do mesmo app mesmo sem você escrever um modificador de acesso.

A diferença entre public e open também confunde facilmente. Em outro módulo, apenas open permite herança e sobrescrita. public pode ser usado, mas não permite herança.

Basta adicionar private para o código ficar muito mais robusto
Basta adicionar private para o código ficar muito mais robusto

Obtendo ocultamento real de informações com private

Vamos ver o exemplo de uma conta no código; só explicar em palavras não é suficiente.

Começaremos com um exemplo ruim, sem encapsulamento.

class BadAccount {
    var balance: Int = 0   // Qualquer pessoa pode modificar externamente
}

let acc = BadAccount()
acc.balance = -99999      // Até valores absurdos entram sem validação
print(acc.balance)
// Saída: -99999

Saldo negativo de 90 mil? As regras desmoronaram completamente.

Agora vamos ocultar o estado interno com private e deixar abertas apenas as rotas de depósito e saque.

class Account {
    private var balance: Int = 0        // Bloquear acesso externo

    func deposit(_ amount: Int) {
        guard amount > 0 else { return }
        balance += amount
    }

    func withdraw(_ amount: Int) -> Bool {
        guard amount > 0, balance >= amount else { return false }
        balance -= amount
        return true
    }

    var currentBalance: Int { balance }  // Permitir apenas leitura
}

let myAccount = Account()
myAccount.deposit(10000)
print(myAccount.withdraw(30000))  // Saldo insuficiente
// Saída: false

Agora balance não pode ser alterado diretamente de fora.

Um código como myAccount.balance = -99999 gera um erro de compilação.

O dinheiro só pode circular por deposit e withdraw, que contêm as regras de validação.

Esse é o poder do ocultamento de informações: impedir desde o início que seja escrito código que viole as regras.


private(set) — permitir leitura e bloquear apenas a escrita

Vamos avançar para um caso mais prático.

É muito comum querer permitir a leitura externa de um valor, mas bloquear apenas sua alteração.

Você pode criar uma propriedade computada separada, como acima, mas o Swift oferece uma opção mais limpa.

class ScoreBoard {
    private(set) var score: Int = 0   // Leitura public, Escrita private

    func addPoint() {
        score += 10
    }
}

let board = ScoreBoard()
board.addPoint()
print(board.score)   // Leitura liberada
// Saída: 10
// board.score = 999  // Esta linha gera um erro de compilação

Ao adicionar private(set), a leitura continua pública, enquanto a permissão de escrita fica restrita ao interior.

Como a pontuação só pode aumentar por meio de addPoint(), você evita que a lógica externa do jogo a manipule.

Uso muito essa sintaxe porque não é preciso criar uma propriedade computada.

Por fora, o acesso ocorre apenas pelas rotas de depósito e saque; o saldo fica bem escondido por dentro
Por fora, o acesso ocorre apenas pelas rotas de depósito e saque; o saldo fica bem escondido por dentro

Quando usar cada modificador?

Veja os critérios mais úteis para quando surgir dúvida no trabalho.

  • Comece por private. Ampliar o escopo quando necessário é mais seguro do que deixá-lo aberto e restringir depois.
  • O valor padrão internal funciona bem na maioria dos apps. Não é preciso escrever tudo explicitamente.
  • public·open só precisam ser considerados ao criar bibliotecas ou frameworks para outras pessoas.
  • Use open somente quando quiser permitir também herança. Caso contrário, public é suficiente.
Situação Decisão
Variável de estado usada apenas internamente private
Você quer permitir somente leitura externa private(set)
Livremente dentro do mesmo app internal (padrão)
Expor publicamente como biblioteca public
Permitir herança e sobrescrita externa open

Lembre-se de uma coisa: o escopo de acesso deve ser aberto sempre da forma mais restrita possível.


Como isso aparece em entrevistas

P. Qual é a diferença entre encapsulamento e ocultamento de informações?

Encapsulamento é o conceito de design que reúne dados e métodos em um objeto, enquanto ocultamento de informações é o princípio de esconder a implementação interna do exterior. Uma resposta clara é que encapsulamento é o recipiente maior, e o ocultamento de informações é realizado dentro dele por meio de modificadores de acesso.

P. Qual é a diferença entre public e open no Swift?

Ambos podem ser acessados de outros módulos, mas apenas open permite herança e sobrescrita de métodos a partir de um módulo externo. Classes public podem ser usadas externamente, mas não herdadas. Vale acrescentar que open é usado somente para abrir pontos de extensão de um framework.


Os modificadores de acesso podem parecer apenas algumas regras de sintaxe para memorizar, mas na verdade treinam o raciocínio de projetar quem pode alterar determinado valor.

Digite você mesmo o exemplo da conta e tudo ficará claro. Recomendo começar adicionando private em um projeto pequeno!

Continue lendo