Ez a kvíz a modul eddigi anyagát fedi le: a trait-ek és impl blokkok, a default metódusok, a dyn Trait és a statikus/dinamikus dispatch, a generikák és trait bound-ok, a monomorfizáció, valamint az Iterator trait és a saját iterátor implementálása. Ne siess, próbáld meg fejben (vagy papíron) megválaszolni a kérdést, mielőtt kinyitod a megoldást.

Trait-ek, impl blokkok, default metódusok

1. kérdés. Mit ír ki ez a kód?

trait Greet {
    fn name(&self) -> String;
    fn greet(&self) -> String {
        format!("Szia, {}!", self.name())
    }
}

struct Dog;
impl Greet for Dog {
    fn name(&self) -> String {
        "Buksi".to_string()
    }
}

fn main() {
    let d = Dog;
    println!("{}", d.greet());
}
Megoldás"Szia, Buksi!" — a `Dog` csak a `name` metódust implementálja, a `greet` default metódust a trait definíciója adja, és az felhasználja a `name` eredményét.

2. kérdés. Melyik állítás igaz a default metódusokra?

A) Minden implementáló típusnak felül kell írnia. B) Csak akkor futnak, ha a típus nem implementál semmit. C) Használhatók anélkül is, hogy egy típus felülírná őket, de felülírhatók. D) Nem hívhatnak más trait-metódust.

MegoldásC) A default metódus a trait törzsében kap implementációt, ezt bármelyik `impl` felülírhatja, de nem kötelező.

dyn Trait és dispatch

3. kérdés. Fordul-e ez a kód?

trait Shape {
    fn area(&self) -> f64;
}

struct Circle { radius: f64 }
impl Shape for Circle {
    fn area(&self) -> f64 { std::f64::consts::PI * self.radius * self.radius }
}

fn main() {
    let shapes: Vec<Box<dyn Shape>> = vec![Box::new(Circle { radius: 2.0 })];
    for s in &shapes {
        println!("{:.2}", s.area());
    }
}
MegoldásIgen, lefordul, és `12.57`-et ír ki. A `Shape` object-safe trait, tehát `Box`-ben tárolható, a dinamikus dispatch futásidőben a helyes `area` implementációt hívja meg.

4. kérdés. Mi a fő különbség a statikus és a dinamikus dispatch között?

MegoldásStatikus dispatch (generikák, monomorfizáció) esetén a fordító már fordításkor tudja, melyik konkrét típus metódusát kell hívni, ezért nincs futásidejű overhead. Dinamikus dispatch (`dyn Trait`) esetén ez futásidőben, egy vtable-en keresztül derül ki, ára van egy kis teljesítményveszteség, de cserébe egy gyűjteményben különböző típusok is elférnek.

Generikák, trait bound, monomorfizáció

5. kérdés. Fordul-e ez a kód, és ha nem, miért?

fn largest<T>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in list {
        if item > largest {
            largest = item;
        }
    }
    largest
}
MegoldásNem fordul: a `>` operátor a `PartialOrd` trait-et igényli, de a `T` típusparaméterre nincs trait bound megadva. A javítás: `fn largest(list: &[T]) -> &T`.

6. kérdés. Mire jó a where klóz a trait bound-ok megadásakor?

MegoldásUgyanazt fejezi ki, mint a `` szintaxis, de olvashatóbbá teszi a szignatúrát, ha több típusparaméter vagy összetettebb bound van — a `where` blokk a paraméterlista után, elkülönítve sorolja fel a feltételeket.

7. kérdés. Mi a monomorfizáció?

A) Futásidőben a generikus függvényből egyetlen közös kód generálódik. B) Fordításkor a fordító minden konkrét típushoz külön, specializált kódot generál a generikus függvényből. C) A dyn Trait másik neve. D) A trait-öröklés szinonimája.

MegoldásB) A monomorfizáció miatt a generikus kód gyakorlatilag ugyanolyan gyors, mint ha kézzel írtad volna meg típusonként — ez az ára a nagyobb bináris méretnek.

Iterator trait

8. kérdés. Mit ír ki ez a kód?

fn main() {
    let v = vec![1, 2, 3, 4, 5];
    let sum: i32 = v.iter().filter(|&&x| x % 2 == 0).map(|x| x * 10).sum();
    println!("{}", sum);
}
Megoldás`60` — a `filter` a páros elemeket (2 és 4) tartja meg, a `map` mindegyiket megszorozza 10-zel (20, 40), a `sum` pedig összeadja őket.

9. kérdés. Egy saját típushoz Iterator implementálásakor melyik metódust kötelező megadni, és mit kell visszaadnia?

MegoldásA `next(&mut self) -> Option` metódust kötelező implementálni. Ha van még elem, `Some(elem)`-et ad vissza és lépteti az állapotot, ha nincs, `None`-t — ez a `map`, `filter`, `collect` és a többi adapter alapja is.

Hogyan tovább

Ha a 3–4. és 7. kérdésnél elakadtál, érdemes visszalapozni a "Statikus vs dinamikus dispatch" és a "Generikák és trait bound" leckékhez. Ha a 8–9. kérdés nehezen ment, nézd át újra a "Saját iterátor írása" leckét. A következő leckében a lifetime annotációkkal ismerkedsz meg — azzal a szintaxissal, amivel a fordítónak jelzed, hogy meddig érvényesek a referenciáid.