Traits as parameters
- Rust course
- Intermediate
- Lesson 4/115
- 4 min
Use traits as function parameters.
Traits as parameters
A function can ask not for a specific type but for a specific behaviour. The impl Trait syntax means "any type implementing this trait":
trait Ozet {
fn ozet(&self) -> String;
}
fn duyur(x: &impl Ozet) -> String {
format!("Yeni: {}", x.ozet())
}duyur now works with every type implementing Ozet: news, tweets, emails... Inside the function only the trait's methods can be used.
Generic syntax
impl Trait is in fact shorthand for a generic type parameter. The two forms are equivalent:
fn duyur(x: &impl Ozet) -> String { .. }
fn duyur<T: Ozet>(x: &T) -> String { .. }The difference shows with several parameters: fn f(a: &impl Ozet, b: &impl Ozet) accepts two different types; fn f<T: Ozet>(a: &T, b: &T) requires both to be of the same type.
Practice Announcement
Define trait Ozet and implement it for Haber { konu: String } (summary: konu) and Tweet { yazar: String, metin: String } (summary: @yazar: metin). With fn duyur(x: &impl Ozet) -> String, print the news "Rust 2.0 çıktı" and the tweet ece/merhaba on separate lines.
Starter code
fn main() {
// buraya yaz
}Sample solution
trait Ozet {
fn ozet(&self) -> String;
}
struct Haber {
konu: String,
}
struct Tweet {
yazar: String,
metin: String,
}
impl Ozet for Haber {
fn ozet(&self) -> String {
self.konu.clone()
}
}
impl Ozet for Tweet {
fn ozet(&self) -> String {
format!("@{}: {}", self.yazar, self.metin)
}
}
fn duyur(x: &impl Ozet) -> String {
format!("Yeni: {}", x.ozet())
}
fn main() {
let h = Haber { konu: String::from("Rust 2.0 çıktı") };
let t = Tweet { yazar: String::from("ece"), metin: String::from("merhaba") };
println!("{}", duyur(&h));
println!("{}", duyur(&t));
}Expected output
Yeni: Rust 2.0 çıktı Yeni: @ece: merhaba
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Inside <code>fn duyur(x: &impl Ozet)</code>, can the field <code>x.konu</code> be accessed?
- No; the compiler only knows what Ozet offers Correct answer
- Yes, if the type is Haber
- Yes, always
- Only with unsafe
Explanation: Since the function can be called with any type, only the methods in the contract can be used safely.
2 Ask for a behaviour
fn duyur(x: &____ Ozet) -> String {
format!("Yeni: {}", x.ozet())
}
fn duyur(x: &impl Ozet) -> String {
format!("Yeni: {}", x.ozet())
}
Explanation: &impl Ozet accepts a reference to any type implementing Ozet.
3 Signature and what it accepts
| Term | Meaning |
|---|---|
fn f(x: &impl Ozet) |
Any type implementing Ozet |
fn f<T: Ozet>(x: &T) |
The same, generic form |
fn f<T: Ozet>(a: &T, b: &T) |
Both the same type |
fn f(x: &Haber) |
Only Haber |