I am modeling an API where method overloading would be a good fit. My naïve attempt failed:
// fn attempt_1(x: int) {}
// fn attempt_1(x: f32) {}
// Error: duplicate definition of value `attempt_1`
I then added an enum and worked through to:
enum IntOrFloat {
Int(int),
Float(f32),
}
fn attempt_2(x: IntOrFloat) {}
fn main() {
let i: int = 1;
let f: f32 = 3.0;
// Can't pass the value directly
// attempt_2(i);
// attempt_2(f);
// Error: mismatched types: expected `IntOrFloat`
attempt_2(Int(i));
attempt_2(Float(f));
// Ugly that the caller has to explicitly wrap the parameter
}
Doing some quick searches, I've found some references that talk about overloading, and all of them seem to end in "we aren't going to allow this, but give traits a try". So I tried:
enum IntOrFloat {
Int(int),
Float(f32),
}
trait IntOrFloatTrait {
fn to_int_or_float(&self) -> IntOrFloat;
}
impl IntOrFloatTrait for int {
fn to_int_or_float(&self) -> IntOrFloat { Int(*self) }
}
impl IntOrFloatTrait for f32 {
fn to_int_or_float(&self) -> IntOrFloat { Float(*self) }
}
fn attempt_3(x: &IntOrFloatTrait) {}
fn main() {
let i: int = 1;
let f: f32 = 3.0;
attempt_3(&i);
attempt_3(&f);
// Better, but the caller still has to explicitly take the reference
}
Is this the closest I can get to method overloading? Is there a cleaner way?
Yes, there is, and you almost got it already. Traits are the way to go, but you don't need trait objects, use generics:
See it working here.