Rust では、はメソッド (および)Clone
を指定する特性です。 や などの一部の特性はfnを指定します。実装に両方が必要なのはなぜでしょうか。違いは何でしょうか。clone
clone_from
StrSlice
CloneableVector
to_owned
両方の方法を備えた 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);
最初の例は機能するのに、2 番目の例は機能しないのはなぜでしょうか?
ベストアンサー1
.clone()
はレシーバを返します。clone()
は を&str
返します&str
。 が必要な場合はString
、別のメソッド (この場合は ) が必要です.to_owned()
。
ほとんどの型の場合、clone()
は基になる型でのみ定義され、参照型では定義されていないため、十分です。ただし、str
および の場合、は参照型 (および) で実装されているため、型が間違っています。また、 は所有型 (および) で実装されているため、その場合は別の所有値を返します。[T]
clone()
&str
&[T]
String
Vec<T>
clone()
最初の例は、c1
とs1
(およびc2
とs2
) が同じ型であるため機能します。2 番目の例は、同じ型ではないため (c1
でString
あるのに対しs1
は&str
)、機能しません。これは、別々のメソッドが必要である理由を示す完璧な例です。
現在の Rust では、どちらもコンパイルされますが、 は でtest_clone()
c1
、&str
は ですtest_to_owned()
。RustString
は値の自動参照と逆参照に関してより寛容になったので、コンパイルされるのは間違いありません。この特定の例では、 のc1 == s1
行は であるかのようにコンパイルされると思います&*c1 == s1
。関係する型を証明したい場合は、 などの意図的な型エラーを追加できますlet _: i32 = c1;
。エラー メッセージには型が表示されます。