Прежде всего, осторожно.String
! = CString
.И s.test(var)
не выдаст ничего, кроме ошибки, поскольку ваш test
метод не принимает никаких параметров, кроме self
.
Теперь о том, что на самом деле происходит.
Когда вы определяете метод расширения, как вы, определяя черту, затем реализуете ее для &_ str
, но не для String
, а затем пытаетесь вызвать его, компилятор неявно выполняет разыменование (поскольку String
реализует Deref
в &_ str
).
В результате, ваша main
функция может быть записана для ясности как:
fn main() {
let s = String::from("123456789");
println!("{}", (s.deref()).test());
}
и полностью аналогична тому, что компилятор выполняет под-капот.По сути, компилятор увидел, что вы пытаетесь использовать это, и сделал это для вас.
Я должен предупредить вас - ваш код очень странный во многих отношениях:
- Обычно такие методы черт реализуют на объектах, а не на их
Deref
аналоге, именно для того, чтобы избежать этого уровня косвенности - Ваша реализация использует ссылку.Подумайте об этом на мгновение.
Гораздо лучший и менее косвенный способ написать это так:
pub trait Foo {
fn test(&self) -> String;
}
impl Foo for str {
fn test(&self) -> String {
String::from("da")
}
}
fn main() {
let s = String::from("123456789");
println!("{}", s.test());
}
Вы ничего не жертвуете, функциональность остается идентичной, но:
- Вы больше не используете ненужную ссылку
- Вы больше не заставляете компилятор без необходимости выводить
deref
вызов