Компилятор Rust конвертирует String в & str неявно? - PullRequest
0 голосов
/ 25 декабря 2018

Я реализовал черту Foo для &'a str, но когда я вызываю метод test для std::string::String, он работает.Я проверил свой код и уверен, что не реализую черту для String, поэтому компилятор Rust неявно преобразует String в str?

Код нравится так:

pub trait Foo {
    fn test(self) -> String;
}

impl<'a> Foo for &'a str {
    fn test(self) -> String {
        String::from("da")
    }
}

fn main() {
    let s = String::from("123456789");
    println!("{}", s.test());
}

Плагин Rust для IDE Jetbrains не может найти метод test для String, но он работает хорошо.

Почему этот код работает?

1 Ответ

0 голосов
/ 25 декабря 2018

Прежде всего, осторожно.String! = CStrings.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 вызов
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...