Rust
Traits as parameters
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.
Exercise 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.
Show example 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));
}
Test yourself
-
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
- Yes, if the type is Haber
- Yes, always
- Only with unsafe
Show answer
No; the compiler only knows what Ozet offers — Since the function can be called with any type, only the methods in the contract can be used safely.
-
Ask for a behaviour
fn duyur(x: &____ Ozet) -> String {
format!("Yeni: {}", x.ozet())
}
Show answer
fn duyur(x: &impl Ozet) -> String {
format!("Yeni: {}", x.ozet())
}
-
Signature and what it accepts
- 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
Next lesson: Multiple traits