Object safety¶
W tym zadaniu zajmiemy się dwoma pokrewnymi zagadnieniami: dynamic dispatch oraz object safety.
Dany jest trait Musician
oraz skończony zbiór typów implementujących ten trait:
trait Musician {
fn play(&self);
}
mod my_band {
pub struct Singer;
impl super::Musician for Singer {
fn play(&self) { println!(":studio_microphone:"); }
}
pub struct Guitarist;
impl super::Musician for Guitarist {
fn play(&self) { println!(":guitar:"); }
}
pub struct Pianist;
impl super::Musician for Pianist {
fn play(&self) { println!(":musical_keyboard:"); }
}
pub struct Drummer;
impl super::Musician for Drummer {
fn play(&self) { println!(":drum:"); }
}
}
1. Zaimplementuj funkcję rehearse
z odpowiednią sygnaturą, która przyjmuje dowolną kolekcję musicians
(tzn. obiektów potencjalnie różnych typów, z których każdy implementuje Musician
) i wywołuje na każdym elemencie play
:
fn rehearse(musicians: ???) {
for musician in musicians {
musician.play();
}
}
Przetestuj swoje rozwiązanie.
2. Dodaj nową metodę do traitu Musician
:
trait Musician {
fn play(&self);
fn tune_to(&self, other: &Self) {
println!("Tuning...");
}
}
Spróbuj uruchomić program ponownie. Napraw go NIE ZMIENIAJĄC KODU TRAITU.
Losowość z odzysku¶
Czasem w testach potrzebujemy losowości. W części przypadków wystarcza nam deterministyczny generator liczb pseudolosowych, który zawsze zwraca te same wartości, natomiast w innych potrzebujemy prawdziwej losowości (tzn. żeby przy każdym odpaleniu testów sprawdzać inne wartości). W drugim scenariuszu bardzo przydatne jest, aby w razie błędu testy były w stanie powtórzyć losowe zachowanie, które doprowadziło do błędu. Innymi słowy, żebyśmy byli w stanie zreprodukować warunki, które doprowadziły testy do porażki.
Przygotuj nowy typ TestSeed
:
pub struct TestSeed([u8; 32]);
Założenia:
- można utworzyć tylko jeden obiekt
TestSeed
na wątek (thread), - domyślnie,
TestSeed
jest losowy (można korzystać zrand::thread_rng
), - ustawiając zmienną środowiskową
TEST_SEED
na niepustą wartość, możemy wymusić ustawienie konkretnego ziarna (tzn. nadpisać domyślną losowość w konstruktorze), - w przypadku gdy wątek panikuje, upewniamy się, że
TestSeed
jest zapisywany do plikurecover_test_seed
.
Przetestuj swoje rozwiązanie.
Polecam skorzystać z rand::{rngs::StdRng, Rng, SeedableRng}
oraz once_cell
.