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);
なぜ最初の例は機能するが2番目の例は機能しないのですか?
.clone()
はそのレシーバーを返します。 _&str
_に対するclone()
は、_&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
_はString
であり、test_to_owned()
では_&str
_です。 Rustは値の自動参照と逆参照についてより寛大になりました。この特定の例では、_c1 == s1
_行が_&*c1 == s1
_。関連する型を証明したい場合は、_let _: i32 = c1;
_などの意図的な型エラーを追加すると、エラーメッセージに型が表示されます。