В Rust, в чем разница между clone() и to_owned()?
В Rust, Clone
- это признак, который указывает метод Clone
(и clone_from
). Некоторые черты, такие как StrSlice
и CloneableVector
, указывают to_owned
fn. Для чего нужна реализация? В чем разница?
Я провел эксперимент с строками Rust, которые имеют оба метода, и демонстрирует, что есть разница, но я не понимаю:
fn main() {
test_clone();
test_to_owned();
}
// compiles and runs fine
fn test_clone() {
let s1: &'static str = "I am static";
let s2 = "I am boxed and owned".to_string();
let c1 = s1.clone();
let c2 = s2.clone();
println!("{:?}", c1);
println!("{:?}", c2);
println!("{:?}", c1 == s1); // prints true
println!("{:?}", c2 == s2); // prints true
}
fn test_to_owned() {
let s1: &'static str = "I am static";
let s2 = "I am boxed and owned".to_string();
let c1 = s1.to_owned();
let c2 = s2.to_owned();
println!("{:?}", c1);
println!("{:?}", c2);
println!("{:?}", c1 == s1); // compile-time error here (see below)
println!("{:?}", c2 == s2);
}
Ошибка времени компиляции для примера to_owned
:
error: mismatched types: expected `~str` but found `&'static str`
(str storage differs: expected `~` but found `&'static `)
clone.rs:30 println!("{:?}", c1 == s1);
Почему первый пример работает, но не второй?
Ответы
Ответ 1
.clone()
возвращает свой ресивер. clone()
на a &str
возвращает a &str
. Если вы хотите String
, вам нужен другой метод, который в этом случае .to_owned()
.
Для большинства типов clone()
достаточно, потому что он определен только для базового типа, а не для ссылочного типа. Но для str
и [T]
, clone()
реализуется в ссылочном типе (&str
и &[T]
), и поэтому он имеет неправильный тип. Он также реализован на принадлежащих типах (String
и Vec<T>
), и в этом случае clone()
вернет другое принадлежащее ему значение.
Ваш первый пример работает, потому что c1
и s1
(и c2
и s2
) имеют одинаковые типы. Ваш второй пример завершился неудачей, потому что они не (c1
есть String
, тогда как s1
- &str
). Это прекрасный пример того, почему необходимы отдельные методы.