Summary - Advanced traits
- Rust course
- Advanced
- Lesson 65/81
- 5 min
Combine associated types and supertraits to write a Graph trait.
Advanced traits summary
Associated types (type Oge;) are types an implementation picks once; associated constants (const N: u32;) are compile-time values belonging to the type. GATs add a lifetime or type parameter to an associated type. Supertraits (trait A: B) declare dependencies. The newtype pattern works around the orphan rule and gives type safety. Together these tools let you define abstract structures like graphs independently of types.
A graph trait
When algorithms are written over a trait, they work with any graph representation (adjacency list, matrix):
trait Graf {
type Dugum;
fn komsular(&self, d: &Self::Dugum) -> Vec<Self::Dugum>;
fn kenar_sayisi(&self) -> usize;
}
struct KomsulukListesi(Vec<Vec<usize>>);
impl Graf for KomsulukListesi {
type Dugum = usize;
fn komsular(&self, d: &usize) -> Vec<usize> {
self.0[*d].clone()
}
fn kenar_sayisi(&self) -> usize {
self.0.iter().map(|k| k.len()).sum()
}
}Practice Graph
Write the Graf trait above and the KomsulukListesi implementation. For the graph vec![vec![1, 2], vec![2], vec![0]], print the neighbours of node 0 ({:?}) and the number of edges, separated by a space.
Starter code
fn main() {
// buraya yaz
}Sample solution
trait Graf {
type Dugum;
fn komsular(&self, d: &Self::Dugum) -> Vec<Self::Dugum>;
fn kenar_sayisi(&self) -> usize;
}
struct KomsulukListesi(Vec<Vec<usize>>);
impl Graf for KomsulukListesi {
type Dugum = usize;
fn komsular(&self, d: &usize) -> Vec<usize> {
self.0[*d].clone()
}
fn kenar_sayisi(&self) -> usize {
self.0.iter().map(|k| k.len()).sum()
}
}
fn main() {
let g = KomsulukListesi(vec![vec![1, 2], vec![2], vec![0]]);
println!("{:?} {}", g.komsular(&0), g.kenar_sayisi());
}Expected output
[1, 2] 4
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 In a <code>Graf</code> trait, why should the node type be an associated type?
- For performance
- It isn't needed
- Each graph structure has a single node type and it needn't be written when using it Correct answer
- Generics are forbidden
Explanation: Signatures like fn yol<G: Graf>(g: &G, a: G::Dugum) stay simple; with a generic parameter, Graf<D> would need D everywhere.
2 Node type
impl Graf for KomsulukListesi {
type ____ = usize;
..
}
impl Graf for KomsulukListesi {
type Dugum = usize;
..
}
Explanation: The implementation sets the associated node type to usize.
3 Group summary
| Term | Meaning |
|---|---|
type X; |
Associated type |
const N: u32; |
Associated constant |
trait A: B |
Supertrait |
struct W(T); |
Newtype |