Swift e Objective-C

Class e struct em Swift: o que uma cópia ainda compartilha

Compare um valor, uma referência e um struct com referência interna. Veja quais alterações se propagam e por que struct não significa cópia profunda.

2 min de leitura
Imagem de capa de Class e struct em Swift: o que uma cópia ainda compartilha

Comece com struct para modelos que representam valores e escolha class quando precisar de identidade ou estado de objeto compartilhado. Envolver um objeto em struct não o torna independente nem automaticamente seguro entre threads.

Mecanismo e decisão de projeto

Atribuir um struct copia seus valores armazenados. Se uma propriedade contém uma referência de classe, a referência é copiada e o objeto continua compartilhado. Isso é diferente de cópia profunda e segurança entre threads. Herança e APIs de objetos Objective-C também influenciam. Fonte primária

Código reproduzível

O experimento copia o inteiro de Point, uma referência Box e um Envelope que contém Box. Separa alterar uma propriedade do objeto de substituir o box da cópia por outro objeto. As precondições verificam original e cópia em cada etapa.

Este exemplo independente foi executado em 2026-10-23 com Apple Swift 6.4 para arm64 macOS, no modo de linguagem Swift 6. Não requer rede nem pacotes adicionais.

Baixar o arquivo Swift completo

Execute o comando na pasta do download. As precondições interrompem a execução se uma verificação falhar. Não use -Ounchecked: essa opção remove as verificações.

swift -swift-version 6 swift-class-vs-struct.swift
struct Point { var x: Int }
final class Box {
    var x: Int
    init(_ x: Int) { self.x = x }
}
struct Envelope { var box: Box }

let point = Point(x: 0)
var copiedPoint = point
copiedPoint.x = 10
precondition(point.x == 0 && copiedPoint.x == 10)

let box = Box(0)
let copiedReference = box
copiedReference.x = 10
precondition(box === copiedReference && box.x == 10)

let envelope = Envelope(box: Box(0))
var copiedEnvelope = envelope
copiedEnvelope.box.x = 20
precondition(envelope.box.x == 20)
copiedEnvelope.box = Box(30)
precondition(envelope.box.x == 20 && copiedEnvelope.box.x == 30)

print("struct=0,10 class=10,10 nested-reference=20,20 replacement=20,30")

Saída registrada e interpretação

struct=0,10 class=10,10 nested-reference=20,20 replacement=20,30

Point fica com 0 e 10; as referências Box compartilham 10. Alterar o objeto pela cópia de Envelope faz ambos observarem 20. Substituir seu box por Box(30) mantém o original em 20. Independência da propriedade e identidade compartilhada são coisas distintas.

Escopo e limitações

Este experimento sequencial verifica semântica de cópia, não condições de corrida ou desempenho. Compartilhar uma variável mutável ou referência interna ainda exige isolamento ou sincronização. A verificação Sendable do Swift 6 não equivale a declarar struct.

O que verificar em seguida

Liste os estados que devem mudar juntos após copiar o modelo. Se o compartilhamento de referências não for intencional, considere valores imutáveis ou uma política explícita de clonagem. Para copiar armazenamento grande com eficiência, siga para o experimento CoW.

Experimento relacionado

Fontes e verificação