Rust Generic Methods
Generic methods are methods on a generic struct. A method can declare its own type letters, for that one method only.
Struct letters come back after impl
Declare the struct's letters again after the word impl. They belong to the struct.
impl<T, U> Point<T, U> {
// every method in here works for all T and U
}A method can bring its own letters
mixup needs two more letters, and they are declared after the method name — they live for that one method only.
fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
Point { x: self.x, y: other.y }
}mixup keeps one field from each point
x comes from self, y comes from the other point. This is the closing program's own call:
let p3 = p1.mixup(p2);
println!("p3.x = {}, p3.y = {}", p3.x, p3.y);An impl for one concrete type only
Write the impl with real types and no letters. Only those values gain the method.
impl Point<f32, f32> {
fn distance(&self) -> f32 {
(self.x * self.x + self.y * self.y).sqrt()
}
}Only float points can call distance
A concrete-only method may use float-only tools, like sqrt, safely.
let c = Point { x: 3.0, y: 4.0 };
println!("distance = {}", c.distance());Example
struct Point<T, U> { x: T, y: U }
impl<T, U> Point<T, U> {
fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
Point { x: self.x, y: other.y }
}
}
impl Point<f32, f32> {
fn distance(&self) -> f32 { (self.x * self.x + self.y * self.y).sqrt() }
}
fn main() {
let p1 = Point { x: 5, y: 10.4 };
let p2 = Point { x: "Hello", y: 'c' };
let p3 = p1.mixup(p2);
println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
let c = Point { x: 3.0, y: 4.0 };
println!("distance = {}", c.distance());
}Key points
- A small concrete impl keeps the general type simple and honest.
- A method on a generic struct works with the struct's type letters.
In this example, p1 holds an integer and a float, and p2 holds text and a char. mixup keeps p1.x, which is 5, and takes p2.y, which is c, so p3 prints p3.x = 5, p3.y = c. The letters V and W existed only for that call. Below, c is a point of two f32 values. So it alone can use distance. 3 squared plus 4 squared is 25. The square root is 5.
Note
If a method does not fit every T, do not force it into the general impl.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
Where are the letters V and W in mixup declared?