В Rust нет перегрузки функций: вы не можете определить несколько функций с одним и тем же именем, но с разными аргументами.
Однако я обнаружил следующий трюк, из-за которого создается впечатление, что существует перегрузка функций. Обратите внимание, как в main()
я могу вызывать example.apply(...)
с разными типами:
struct Example;
trait Apply<T, R> {
fn apply(&self, value: T) -> R;
}
impl Apply<i32, i32> for Example {
fn apply(&self, value: i32) -> i32 {
value * 2
}
}
impl Apply<&str, String> for Example {
fn apply(&self, value: &str) -> String {
format!("Hello, {}", value)
}
}
fn main() {
let example = Example;
// Looks like function overloading!
let one = example.apply(12);
let two = example.apply("World");
println!("{}", one);
println!("{}", two);
}
Теперь я хотел бы создать две разные версии черты Apply
: одну для значений, которые равны Copy
и один для значений, отличных от Copy
:
struct Example;
struct NotCopy(i32);
// For types which are Copy
trait ApplyCopy<T: Copy, R> {
fn apply(&self, value: T) -> R;
}
// For types which are not Copy
trait ApplyRef<T, R> {
fn apply(&self, value: &T) -> R;
}
impl ApplyCopy<i32, i32> for Example {
fn apply(&self, value: i32) -> i32 {
value * 2
}
}
impl ApplyRef<NotCopy, String> for Example {
fn apply(&self, value: &NotCopy) -> String {
format!("NotCopy({})", value.0)
}
}
Однако, когда я пытаюсь использовать это, я получаю ошибки:
fn main() {
let example = Example;
let one = example.apply(12); // Error: multiple `apply` found
let two = example.apply(&NotCopy(34)); // Error: multiple `apply` found
println!("{}", one);
println!("{}", two);
}
Одно из сообщений об ошибке:
error[E0034]: multiple applicable items in scope
--> src/main.rs:30:23
|
30 | let one = example.apply(12); // Error: multiple `apply` found
| ^^^^^ multiple `apply` found
|
note: candidate #1 is defined in an impl of the trait `ApplyCopy` for the type `Example`
--> src/main.rs:16:5
|
16 | fn apply(&self, value: i32) -> i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in an impl of the trait `ApplyRef` for the type `Example`
--> src/main.rs:22:5
|
22 | fn apply(&self, value: &NotCopy) -> String {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #1
|
30 | let one = ApplyCopy::apply(&example, 12); // Error: multiple `apply` found
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #2
|
30 | let one = ApplyRef::apply(&example, 12); // Error: multiple `apply` found
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Компилятор жалуется, что не знает, какую apply
функцию вызвать. Я ожидал, что он сможет сделать выбор: i32
не является ссылкой, а Copy
, поэтому apply
черты ApplyCopy
- единственный, который может быть вызван, а &NotCopy(34)
- это ссылка, а поскольку NotCopy
не Copy
, можно вызвать только apply
из ApplyRef
.
Это ограничение компилятора Rust или я что-то упустил?