Подтвердить что ты не робот

В Rust, в чем разница между clone() и to_owned()?

В Rust, Clone - это признак, который указывает метод Cloneclone_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);

Почему первый пример работает, но не второй?

4b9b3361

Ответ 1

.clone() возвращает свой ресивер. clone() на a &str возвращает a &str. Если вы хотите String, вам нужен другой метод, который в этом случае .to_owned().

Для большинства типов clone() достаточно, потому что он определен только для базового типа, а не для ссылочного типа. Но для str и [T], clone() реализуется в ссылочном типе (&str и &[T]), и поэтому он имеет неправильный тип. Он также реализован на принадлежащих типах (String и Vec<T>), и в этом случае clone() вернет другое принадлежащее ему значение.

Ваш первый пример работает, потому что c1 и s1c2 и s2) имеют одинаковые типы. Ваш второй пример завершился неудачей, потому что они не (c1 есть String, тогда как s1 - &str). Это прекрасный пример того, почему необходимы отдельные методы.