Rust
Newtype pattern
Resolve trait conflicts with the newtype pattern.
The newtype pattern
The orphan rule forbids implementing another crate's trait for another crate's type: impl Display for Vec<String> can't be written. The solution is wrapping the type in your own single-field struct; since the wrapper is your type, the implementation is allowed:
struct Liste(Vec<String>);
impl std::fmt::Display for Liste {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "[{}]", self.0.join(", "))
}
}
A newtype adds no runtime cost; in memory it's the same as the inner type.
Newtypes for type safety
Values with the same base type but different meanings can no longer be mixed up:
struct KullaniciId(u64);
struct SiparisId(u64);
fn siparis_bul(id: SiparisId) { .. }
// siparis_bul(KullaniciId(7)); // error: type mismatch
Validation can go in the constructor too: if Eposta::new(s) returns Some only for valid addresses, the rest of the program can trust that every Eposta is valid.
Exercise Printable list
Write the Liste newtype above and its Display implementation. Print Liste(vec!["elma".into(), "armut".into()]) with {}.
Show example solution
use std::fmt;
struct Liste(Vec<String>);
impl fmt::Display for Liste {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]", self.0.join(", "))
}
}
fn main() {
let l = Liste(vec!["elma".into(), "armut".into()]);
println!("{}", l);
}
Test yourself
-
What is the newtype's downside and how is it eased?
- It's slow
- It wastes memory
- No downside
- The inner type's methods are lost; implement Deref or forward the needed ones
Show answer
The inner type's methods are lost; implement Deref or forward the needed ones — Deref opens everything and can weaken the wrapper's purpose; forwarding only the needed methods by hand is more controlled.
-
Wrapper
struct Liste____;
impl std::fmt::Display for Liste { .. }
Show answer
struct Liste(Vec<String>);
impl std::fmt::Display for Liste { .. }
-
Implementation and permission
- impl Display for Vec<String>
- Forbidden
- impl Display for Liste
- Allowed
- KullaniciId(u64)
- Type safety
- size_of::<Liste>()
- Same as Vec
Next lesson: Summary - Advanced traits