2014-03-08 2 views
19

В Rust, Clone - это признак, который определяет метод cloneclone_from). Некоторые черты, такие как StrSlice и CloneableVector, указывают to_owned fn. Для чего нужна реализация? В чем разница?В Rust, в чем разница между clone() и to_owned()?

я сделал эксперимент с ржавчиной строк, которые имеют оба метода, и это свидетельствует о том, что есть разница, но я не понимаю:

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); 

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

+0

Эта ошибка больше не воспроизводится в текущем Rust (см. На [Playground] (http://is.gd/2bYnMW), где я заменил '~" abc "' на '' abc ".to_string()' –

+2

Я обновил пример, чтобы использовать 'to_string()' вместо более старой '~' нотации. Однако интересно, что эта новая версия (ваша игровая площадка) теперь компилируется и выполняется нормально. Было ли изменение в '==' operator/fn, чтобы он мог сравнивать типы '& str' и' String' для равенства значений? – quux00

ответ

19

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

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

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

Смежные вопросы