Cechy równości
Część sekcji Programowanie obiektowe ścieżki Rust w Coddy. Lekcja 38 z 61.
Domyślnie porównywanie dwóch instancji własnej struktury za pomocą == nie działa w Rust. Kompilator nie wie, jak ustalić, czy dwie struktury są równe. Musisz mu to wskazać, implementując cechę PartialEq.
Podobnie jak Debug i Copy, możesz automatycznie wyprowadzić PartialEq:
#[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
Podczas wyprowadzania implementacji PartialEq porównuje każde pole struktury. Dwie instancje są równe tylko wtedy, gdy wszystkie odpowiadające sobie pola są zgodne.
Spotkasz się również z Eq, czyli cechą znacznikową, która wskazuje równość całkowitą, co oznacza, że każda wartość jest równa samej sobie. Większość typów spełnia ten warunek, ale liczby zmiennoprzecinkowe nie (ponieważ NaN != NaN). W przypadku struktur z polami całkowitymi możesz bezpiecznie wyprowadzić obie cechy:
#[derive(PartialEq, Eq)]
struct Coordinate {
x: i32,
y: i32,
}
Eq nie ma własnych metod. Po prostu sygnalizuje, że typ ma równość zwrotną. Niektóre elementy biblioteki standardowej wymagają Eq oprócz PartialEq, dlatego często wyprowadza się obie te cechy jednocześnie dla typów, które się do tego kwalifikują.
Wyzwanie
ŁatwyZbudujmy system dopasowywania kolorów, który pokazuje, jak cechy PartialEq i Eq umożliwiają porównywanie instancji struktur!
Utworzysz dwa pliki, aby uporządkować logikę porównywania kolorów:
color.rs: Zdefiniuj publiczną strukturęColorz trzema publicznymi polami:red,greeniblue(wszystkie typuu8). Wyprowadź zarównoPartialEq, jak iEq, aby można było porównywać dwa kolory za pomocą==. Po wyprowadzeniu tych cech Rust uzna dwa kolory za równe tylko wtedy, gdy wszystkie trzy składowe RGB będą dokładnie takie same.main.rs: Dołącz moduł kolorów i utwórz dwie instancjeColorna podstawie podanych danych wejściowych. Porównaj je za pomocą==i wypisz, czy są takie same.
Wynik powinien wskazywać, czy kolory są takie same:
Color 1: rgb({r1}, {g1}, {b1})
Color 2: rgb({r2}, {g2}, {b2})
Colors match: {true/false}Na przykład dla danych wejściowych 255, 128, 0, 255, 128, 0:
Color 1: rgb(255, 128, 0)
Color 2: rgb(255, 128, 0)
Colors match: trueA dla danych wejściowych 100, 100, 100, 200, 200, 200:
Color 1: rgb(100, 100, 100)
Color 2: rgb(200, 200, 200)
Colors match: falseOtrzymasz sześć wartości wejściowych: wartości RGB pierwszego koloru (trzy wartości), a następnie wartości RGB drugiego koloru (trzy wartości). Każdą z nich sparsuj jako u8.
Spróbuj swoich sił
mod color;
use color::Color;
fn main() {
// Wczytaj sześć wartości 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: Utwórz dwie instancje Color, używając sparsowanych wartości
// TODO: Wypisz Color 1 w formacie: Color 1: rgb(r, g, b)
// TODO: Wypisz Color 2 w formacie: Color 2: rgb(r, g, b)
// TODO: Porównaj oba kolory za pomocą == i wypisz: Colors match: {true/false}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Metody i zachowanie
Wprowadzenie do bloków implementacjiParametr selfMetody modyfikująceFunkcje powiązaneWiele bloków implementacjiŁańcuchowe wywoływanie metodPowtórzenie — działania na prostokącie4Projekt: Wirtualne zwierzątko
Definiowanie zwierzątkaKarmienie zwierzątka7Standardowe cechy
Cecha DebugCecha DisplayClone i CopyCechy równościPowtórka – punkt do wydrukowania10Projekt: System dokumentów
Trait DrawKomponent tekstowy2Hermetyzacja i moduły
Podstawy modułówSłowo kluczowe publicPola prywatneGetterySetteryPodsumowanie — bezpieczna skrytka5Typy generyczne
Struktury generyczneMetody generyczneWiele typów generycznychFunkcje generycznePodsumowanie – punkt współrzędnych8Cechy jako ograniczenia
Składnia ograniczeń cechWiele ograniczeńKlauzula whereZwracanie typów z użyciem cechPodsumowanie — generyczna drukarka11Wzorce projektowe w Rust
Wzorzec NewtypeKompozycjaTrait DropFrom i IntoPodsumowanie — atrapowy inteligentny wskaźnik3Zaawansowane typy wyliczeniowe
Typy wyliczeniowe z danymiMetody typów wyliczeniowychDopasowywanie wariantów danychTyp wyliczeniowy Option — powtórzeniePodsumowanie — typ wyliczeniowy Shape6Definiowanie cech
Czym jest cecha?Implementowanie cechImplementacje domyślneNadpisywanie wartości domyślnychCechy z parametramiPowtórzenie — odtwarzacz multimedialnyPoćwicz samodzielnie: Kompilator Rust online