Newtype pattern
- Rust course
- Advanced
- Lesson 64/81
- 4 min
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 mismatchValidation 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.
Practice Printable list
Write the Liste newtype above and its Display implementation. Print Liste(vec!["elma".into(), "armut".into()]) with {}.
Starter code
use std::fmt;
fn main() {
// buraya yaz
}Sample 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);
}Expected output
[elma, armut]
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 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 Correct answer
Explanation: Deref opens everything and can weaken the wrapper's purpose; forwarding only the needed methods by hand is more controlled.
2 Wrapper
struct Liste____;
impl std::fmt::Display for Liste { .. }
struct Liste(Vec<String>);
impl std::fmt::Display for Liste { .. }
Explanation: A single-field tuple struct is the newtype pattern.
3 Implementation and permission
| Term | Meaning |
|---|---|
impl Display for Vec<String> |
Forbidden |
impl Display for Liste |
Allowed |
KullaniciId(u64) |
Type safety |
size_of::<Liste>() |
Same as Vec |