Dans la Rouille, quelle est la différence entre le clone() et to_owned()?
Dans la Rouille, Clone
est un trait de caractère qui indique le clone
méthode (et clone_from
). Certains traits, comme StrSlice
et CloneableVector
spécifier un to_owned
fn. Pourquoi une mise en œuvre à la fois besoin? Quelle est la différence?
J'ai fait une expérience avec de la Rouille des chaînes, qui ont à la fois des méthodes, et il montre qu'il existe une différence, mais je ne la comprends pas:
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);
}
L'erreur de compilation pour le to_owned
exemple:
error: mismatched types: expected `~str` but found `&'static str`
(str storage differs: expected `~` but found `&'static `)
clone.rs:30 println!("{:?}", c1 == s1);
Pourquoi le premier exemple de travail mais pas la seconde?
- Cette erreur n'est pas reproductible en plus dans le courant de la Rouille (voir le Jeux où j'ai remplacé
~"abc"
avec"abc".to_string()
- J'ai mis à jour l'exemple de l'utilisation
to_string()
plutôt que les anciennes '~' la notation. Cependant, il est intéressant de noter que cette nouvelle version (votre terrain de jeu d'entrée) maintenant compile et fonctionne très bien. Fait un changement dans le==
opérateur/fn arriver afin qu'il puisse comparer&str
etString
types de valeur de l'égalité?
Vous devez vous connecter pour publier un commentaire.
.clone()
retourne son récepteur.clone()
sur un&str
renvoie une&str
. Si vous voulez unString
, vous avez besoin d'une méthode différente, qui dans ce cas est.to_owned()
.Pour la plupart des types,
clone()
est suffisant car il n'est défini sur le type sous-jacent et non pas sur le type de référence. Mais pourstr
et[T]
,clone()
est mis en œuvre sur le type de référence (&str
et&[T]
), et par conséquent, il a le mauvais type. Il est également mis en œuvre sur la propriété de types (String
etVec<T>
), et dans ce casclone()
sera de retour une autre propriété de la valeur.Votre premier exemple fonctionne parce que
c1
ets1
(etc2
ets2
) ont les mêmes types. Votre deuxième exemple échoue parce qu'ils ne le font pas (c1
estString
alors ques1
est&str
). C'est un parfait exemple de pourquoi les méthodes distinctes sont nécessaires.De courant à la Rouille, à la fois maintenant compiler, mais dans
test_clone()
c1
est unString
et danstest_to_owned()
c'est un&str
. Je suis assez sûr qu'il compile que la Rouille est maintenant plus légère automatiquement référencement et déréférencement des valeurs. Dans cet exemple particulier, je crois que lec1 == s1
ligne est compilé comme si elle dit&*c1 == s1
. Si vous souhaitez prouver les types de participer, vous pouvez ajouter délibérée d'une erreur de type, comme leslet _: i32 = c1;
et le message d'erreur indiquera le type.c1 == s1
je pense que se termine la compilation comme&*c1 == s1
, qui est un&str == &str
comparaison. Notez quec1
dans letest_to_owned()
exemple, est encore unString
.