Traits de Igualdade
Parte da seção Object Oriented Programming do Journey de Rust da Coddy — lição 38 de 61.
Comparar duas instâncias de uma struct personalizada com == não funciona por padrão no Rust. O compilador não sabe como determinar se duas structs são iguais — você precisa dizer a ele implementando a trait PartialEq.
Assim como Debug e Copy, você pode derivar PartialEq automaticamente:
#[derive(PartialEq)]
struct Coordinate {
x: i32,
y: i32,
}
let a = Coordinate { x: 5, y: 10 };
let b = Coordinate { x: 5, y: 10 };
let c = Coordinate { x: 3, y: 7 };
println!("{}", a == b); // true
println!("{}", a == c); // false
Quando derivado, PartialEq compara cada campo da struct. Duas instâncias são iguais apenas se todos os seus campos correspondentes coincidirem.
Você também encontrará o Eq, que é uma trait de marcação que indica igualdade total—o que significa que cada valor é igual a si mesmo. A maioria dos tipos satisfaz isso, mas números de ponto flutuante não (porque NaN != NaN). Para structs com campos de números inteiros, você pode derivar ambos com segurança:
#[derive(PartialEq, Eq)]
struct Coordinate {
x: i32,
y: i32,
}
Eq não possui métodos próprios — ele simplesmente sinaliza que o tipo possui igualdade reflexiva. Alguns recursos da biblioteca padrão exigem Eq além de PartialEq, por isso é comum derivar ambos juntos para tipos que se qualificam.
Desafio
FácilVamos construir um sistema de correspondência de cores que demonstra como as traits PartialEq e Eq permitem a comparação entre instâncias de structs!
Você criará dois arquivos para organizar sua lógica de comparação de cores:
color.rs: Defina uma structColorpública com três campos públicos:red,greeneblue(todosu8). Derive tantoPartialEqquantoEqpara que duas cores possam ser comparadas usando==. Quando derivado, o Rust considerará duas cores iguais apenas se todos os três componentes RGB coincidirem exatamente.main.rs: Importe seu módulo de cores e crie duas instâncias deColorusando as entradas fornecidas. Compare-as usando==e imprima se elas coincidem ou não.
Sua saída deve indicar se as duas cores são iguais:
Color 1: rgb({r1}, {g1}, {b1})
Color 2: rgb({r2}, {g2}, {b2})
Colors match: {true/false}Por exemplo, com as entradas 255, 128, 0, 255, 128, 0:
Color 1: rgb(255, 128, 0)
Color 2: rgb(255, 128, 0)
Colors match: trueE com as entradas 100, 100, 100, 200, 200, 200:
Color 1: rgb(100, 100, 100)
Color 2: rgb(200, 200, 200)
Colors match: falseVocê receberá seis entradas: os valores RGB para a primeira cor (três valores), seguidos pelos valores RGB para a segunda cor (três valores). Analise cada um como u8.
Folha de consulta
Para comparar structs personalizadas usando ==, implemente a trait PartialEq derivando-a:
#[derive(PartialEq)]
struct Coordinate {
x: i32,
y: i32,
}
let a = Coordinate { x: 5, y: 10 };
let b = Coordinate { x: 5, y: 10 };
println!("{}", a == b); // true
Quando derivada, a PartialEq compara todos os campos—duas instâncias são iguais apenas se todos os campos correspondentes coincidirem.
A trait Eq é uma trait de marcação (marker trait) que indica igualdade total (cada valor é igual a si mesmo). A maioria dos tipos satisfaz isso, exceto números de ponto flutuante (porque NaN != NaN). Para structs com campos de números inteiros, derive ambas as traits juntas:
#[derive(PartialEq, Eq)]
struct Coordinate {
x: i32,
y: i32,
}
A Eq não possui métodos—ela sinaliza igualdade reflexiva. Alguns recursos da biblioteca padrão exigem Eq além de PartialEq.
Experimente você mesmo
mod color;
use color::Color;
fn main() {
// Lê os seis valores RGB
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let r1: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let g1: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let b1: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let r2: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let g2: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let b2: u8 = input.trim().parse().expect("Invalid input");
// TODO: Criar duas instâncias de Color usando os valores analisados
// TODO: Imprimir Color 1 no formato: Color 1: rgb(r, g, b)
// TODO: Imprimir Color 2 no formato: Color 2: rgb(r, g, b)
// TODO: Comparar as duas cores usando == e imprimir: Colors match: {true/false}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Object Oriented Programming
1Métodos e Comportamento
Introdução a Blocos de ImplementaçãoO Parâmetro SelfMétodos MutáveisFunções AssociadasMúltiplos Blocos de ImplementaçãoEncadeamento de MétodosRecapitulação - Ações de Retângulo4Projeto: Pet Virtual
Definindo o PetAlimentando o Pet7Traits Padrão
A Trait DebugA Trait DisplayClone e CopyTraits de IgualdadeRecapitulação - Ponto Imprimível10Projeto: Sistema de Documentos
A Trait DrawComponente de Texto2Encapsulamento e Módulos
Fundamentos de MódulosA Palavra-chave PublicCampos PrivadosGettersSettersRecapitulação - Cofre Seguro5Genéricos
Structs GenéricasMétodos GenéricosMúltiplos Tipos GenéricosFunções GenéricasRecapitulação - Ponto de Coordenada8Traits como Restrições
Sintaxe de Restrições de TraitRestrições MúltiplasA Cláusula WhereRetornando Tipos com TraitsRecapitulação - Impressora Genérica11Padrões de Projeto em Rust
Padrão NewtypeComposiçãoA Trait DropFrom e IntoRecapitulação - Mock de Smart Pointer3Enums Avançados
Enums com DadosMétodos em EnumsCorrespondência de Variantes de DadosO Enum Option RevisitadoRecapitulação - Enum Shape6Definição de Traits
O que é uma Trait?Implementando TraitsImplementações PadrãoSobrescrevendo PadrõesTraits com ParâmetrosRecapitulação - Media Player