Когда я не должен реализовывать черту для ссылок на разработчиков этой черты?
Если у меня есть черта, и функция, которая принимает универсальный тип, ограниченный этим типом, все работает отлично. Если я пытаюсь передать ссылку на этот тип, я получаю ошибку компиляции.
trait Trait {
fn hello(&self) -> u32;
}
struct Struct(u32);
impl Trait for Struct {
fn hello(&self) -> u32 { self.0 }
}
fn runner<T: Trait>(t: T) { println!("{}", t.hello()) }
fn main() {
let s = Struct(42);
// Works
runner(s);
// Doesn't work
// runner(&s);
// error: the trait `Trait` is not implemented for the type `&Struct`
}
Я могу решить эту проблему, реализовав черту для любой ссылки на тип, который реализует черту:
impl<'a, T> Trait for &'a T where T: Trait {
fn hello(&self) -> u32 { (*self).hello() }
}
Часть информации, которую я пропускаю, это когда мне не следует это реализовывать? Спросил другой способ, почему компилятор не реализует это автоматически для меня? Поскольку в настоящее время этого не происходит, я предполагаю, что должны быть случаи, когда такая реализация была бы невыгодной.
2 ответа
Конкретная черта, которую вы здесь пишете, берет себя только по ссылке, и это единственная причина, по которой это возможно. По этой причине, принимая параметр в runner()
по стоимости, вероятно, нежелательно; вместо этого вы должны взять его по ссылке. Это правило может применяться в целом: если возможно реализовать черту для ссылки, то вместо того, чтобы задаться вопросом "должен ли я ее реализовать?", Вам следует задаться вопросом "зачем мне ее реализовывать?" Для тех случаев, когда вы будете ее использовать, вероятно, следует быть изменены, чтобы взять объект по ссылке в первую очередь.
когда я не должен реализовать это? Спросил другой способ, почему компилятор не реализует это автоматически для меня? Поскольку в настоящее время этого не происходит, я предполагаю, что должны быть случаи, когда такая реализация была бы невыгодной.
Например, сразу пришла в голову черта Default.
pub trait Default {
fn default() -> Self;
}
Я мог бы реализовать это для T, но нет способов автоматически реализовать это для &T.