Semântica de Valor ou de Referência?

Nesse artigo vamos entender um pouco a diferença de “Reference Semantics” e “Value Semantics”.

Primeiro precisamos entender o que é essa semântica que está sendo referenciada. Ela é o modo como é interpretado o código escrito, e as mesmas linhas de código podem ter dois comportamentos diferentes, pois esse comportamento depende de como são estruturadas as coisas que estamos usando nesse trecho.

Por exemplo:

Esse trecho pode estar atribuindo um um Double, Int, Float dependendo de como a variável foi declarada. Ex.:

Semântica de Referência

Como nós trabalhamos com classes, vamos imaginar uma classe que guarda uma velocidade.

Temos também uma classe que representa um carro. Criamos um objeto pra cada e atribuímos um valor para o objeto de velocidade.

Então atribuímos a velocidade atual o objeto de velocidade criado previamente.

Agora vamos criar outro carro, mas queremos que ele ande em uma velocidade diferente.

Aqui surge o problema de usar Semântica de Referência, pois usamos o mesmo objeto de velocidade para as duas características do carro. Nós queríamos somente deixar a velocidade máxima do carro como 200km/h, mas também mudamos velocidade atual.

Uma maneira de corrigir isso é copiando os objetos, mas isso traz outros problemas de legibilidade de código assim como de performance.

Outra maneira é fazer com que os objetos sejam imutáveis, mas isso traz outros problemas de legibilidade e performance, pois gera a necessidade de criar novos objetos toda vez que um valor precisa ser mudado.

Semântica de Valor

Nós já usamos esse conceito em vários lugares, por exemplo:

O comportamento é diferente do exemplo de Semântica de Referência, e se não se comportasse assim nos deixaria louco. O mesmo acontece com CGPoint por exemplo.

Nós podemos utilizar desse conceito para tipos mais complexos, como String que respeita Semântica de Valor em Swift,tornando logicamente separados dois valores.

Em Swift todos os tipos fundamentais (Int, Double, String…), todas as coleções (Array, Set, Dictionary…), tuples, structs, e enums todos estão no mundo de Semântica de Valor.

Outra propriedade importante dessa semântica é a noção de igualdade dos valores, não importa como chegou naquele valor, por exemplo 2 = 1+1, não importa a identidade dele como importa em Semântica de Referência. Com inteiros essa noção é obvia, mas se usar String, da para começar a entender o poder dessa habilidade. ex.:

Para isso usamos o operador ‘==’, a partir do protocolo Equatable, que tem que se comportar de maneira previsível seguindo as regras que usamos já na matemática de:

  • Reflexividade: ‘x == x’ é Verdadeiro
  • Simetria: se ‘x == y’ então ‘y == x’
  • Transitividade: se ‘x == y’ e ‘y == z’ então ‘x == z’

Um exemplo usando CGPoint para implementação de Equatable:

Nós podemos corrigir nosso problema inicial usando essa nova semântica:

Com esses conhecimentos ja podemos fazer tipos que usam a Semântica de Valor mais complexos com composições de outros mais simples sem grandes dificuldades, assim nós ainda temos mutabilidade mas sem os problemas de dois lugares usarem a mesma referência e fazer copias de Value Types é muito muito menos custoso computacionalmente.

Esse artigo foi inspirado na palestra da WWDC15 sessão 414: "Building Better Apps with Value Types in Swift", nela você entenderá melhor os conceitos apresentados e mais exemplos na prática.

--

--