Quando você aprende Objective-C ou Java primeiro e depois migra para Swift, há um ponto que certamente vai encontrar.
É a pergunta: “Como clonar um objeto?”
É fácil sair procurando um método como clone(), mas no Swift quase nunca é necessário.
Vou começar pela conclusão.
Graças a tipos por valor, como structs e arrays, e à otimização Copy-on-Write (cópia adiada), o Swift substitui, no nível da linguagem, o padrão Prototype dos padrões de projeto.
Você não precisa criar um padrão separado para clonar objetos; basta atribuir o valor para obter uma cópia segura.
Neste artigo, vamos entender o que o padrão Prototype pretendia resolver originalmente e como os tipos por valor e o Copy-on-Write do Swift incorporam isso naturalmente, com exemplos.
Para distinguir os tipos de cópia, Cópia rasa vs. cópia profunda é a base. Quando também é necessário clonar classes, Padrão Prototype e NSCopying no Swift mostra a alternativa.
O problema que o padrão Prototype pretendia resolver
O padrão Prototype pertence aos padrões criacionais de GoF.
A ideia é simples: em vez de criar um objeto novo do zero, você clona um objeto existente para obter uma nova instância.
Por que isso era necessário?
Em linguagens como Objective-C e Java, os objetos são principalmente tipos por referência.
Ao atribuir um objeto a uma variável, você copia apenas o endereço que aponta para o mesmo objeto, não o valor.
Por isso, ao alterar A, B também muda.
Para evitar isso, os desenvolvedores criavam métodos como clone() ou copy() para retornar uma “cópia verdadeira”.
O padrão Prototype é uma ferramenta para esse tipo de situação.
- Quando criar objetos é caro e você precisa de vários objetos semelhantes
- Quando precisa de uma cópia independente sem alterar o original
- Quando quer que o próprio objeto seja responsável pela lógica de clonagem
Tipos por valor no Swift: basta atribuir para copiar
Structs e enums do Swift, além de tipos padrão como Array, Dictionary e String, são todos tipos por valor.
Tipos por valor são copiados quando atribuídos ou passados para uma função.
Em outras palavras, a linguagem cria a cópia automaticamente.
O exemplo deixa isso muito mais claro.
struct Point { var x: Int; var y: Int }
var a = Point(x: 1, y: 2)
var b = a // o valor é copiado neste momento
b.x = 99
// a.xcontinua 1, b.xapenas 99
b = aEsta linha substitui o trabalho que o clone() do padrão Prototype fazia.
Não é necessário criar um método de clonagem separado nem adotar um protocolo de cópia.
O original a fica protegido com segurança, e b se torna uma cópia totalmente independente.
Os bugs complicados causados por objetos interligados nem podem ocorrer nessa estrutura.
Como o Copy-on-Write resolve o problema de desempenho
Aqui surge uma preocupação natural.
“Se copiarmos tudo a cada atribuição, arrays grandes não ficarão lentos demais?”
É uma observação válida. Por isso o Swift usa Copy-on-Write, ou CoW.
O princípio do CoW é o seguinte.
Ao atribuir um valor, o armazenamento interno é compartilhado primeiro. A cópia real dos dados é adiada.
Quando um dos dois tenta modificar o valor, a cópia real finalmente acontece.
| Momento | Operação interna | Custo |
|---|---|---|
| Ao atribuir | Armazenamento compartilhado (apenas referência) | Muito baixo |
| Ao apenas ler | O compartilhamento continua | Sem cópia |
| Ao modificar o valor | A cópia real acontece aqui | Ocorre somente neste momento |
Assim, os desenvolvedores aproveitam a segurança dos tipos por valor sem pagar custos de cópia desnecessários.
Se você apenas ler e não modificar, nenhuma cópia será feita.
Tipos da biblioteca padrão, como Array, Dictionary, Set e String, já têm CoW integrado.
A linguagem e a biblioteca padrão cuidam disso automaticamente, sem que precisemos implementar nada.
Ainda existem casos em que o padrão Prototype é necessário?
“Então o padrão Prototype está completamente morto no Swift?”
Não necessariamente.
Há situações em que você precisa usar classes: quando a semântica de referência é indispensável, quando precisa de interoperabilidade com Objective-C ou quando a herança é necessária.
Nesses casos, se precisar de uma cópia independente de uma instância de classe, ainda terá de implementar a lógica de clonagem por conta própria.
O Swift oferece o protocolo NSCopying e copy(), que são essencialmente a forma tradicional do padrão Prototype.
Fica mais fácil pensar na divisão desta forma.
- Usar structs e tipos por valor → A atribuição conclui a cópia; o padrão Prototype é desnecessário
- É obrigatório usar classes → Implemente a lógica de clonagem quando necessário; é aqui que o padrão sobrevive
Por isso a comunidade Swift costuma recomendar: “Considere primeiro os tipos por valor”.
Quando tipos por valor são o padrão, o problema de clonagem desaparece.
Resumo
Tentar adaptar à força um padrão de projeto de uma linguagem desconhecida muitas vezes deixa o código mais complexo.
No Swift, basta lembrar que tipos por valor e Copy-on-Write ocupam naturalmente o lugar do padrão Prototype para tornar as preocupações com clonagem muito mais leves.
Na próxima vez que precisar copiar um objeto, antes de procurar clone(), pense: “Será que posso transformar isso em uma struct?”. Isso certamente ajudará.

