I find this is particularly useful pattern to allow method overloading:
struct Foo {
value:uint
}
trait HasUIntValue {
fn as_uint(self) -> uint;
}
impl Foo {
fn add<T:HasUIntValue>(&mut self, value:T) {
self.value += value.as_uint();
}
}
impl HasUIntValue for int {
fn as_uint(self) -> uint {
return self as uint;
}
}
impl HasUIntValue for f64 {
fn as_uint(self) -> uint {
return self as uint;
}
}
#[test]
fn test_add_with_int()
{
let mut x = Foo { value: 10 };
x.add(10i);
assert!(x.value == 20);
}
#[test]
fn test_add_with_float()
{
let mut x = Foo { value: 10 };
x.add(10.0f64);
assert!(x.value == 20);
}
Is there any meaningful downside to doing this?
There is at least one downside: it cannot be an afterthought.
In C++, ad-hoc overloading allows you to overload a function over which you have no control (think 3rd party), whereas in Rust this is not actually doable.
That being said, ad-hoc overloading is mostly useful in C++ because of ad-hoc templates, which is the only place where you cannot know in advance which function the call will ultimately resolve to. In Rust, since templates are bound by traits, the fact that overloading cannot be an afterthought is not an issue since only the traits functions can be called anyway.
No, there is no downside; this is exactly the pattern to implement overloading in Rust.
There are a number of types in the standard library which do exactly this. For example, there is BytesContainer trait in path module, which is implemented for various kinds of strings and vectors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With