Open1
Rust Conversion
🧭 全体の地図:型変換の4系統
種類 | 概念 | 例 | 安全性 | 主な用途 |
---|---|---|---|---|
as |
プリミティブキャスト | x as f64 |
❗安全でない場合あり | 数値変換や生ポインタ変換 |
From / Into
|
安全な変換(常に成功) |
String::from("hi") / "hi".into()
|
✅常に成功 | 明示的な型変換 |
TryFrom / TryInto
|
失敗するかもしれない変換 | u8::try_from(300)? |
⚠️失敗の可能性あり | 制約付き変換 |
AsRef / AsMut
|
参照として借用変換 | path.as_ref() |
✅安全 | 汎用関数での借用変換 |
as
:型キャスト(C言語っぽいけど注意!)
🧩 1. as
は「コンパイラに型を強制的に変換させる」演算子です。
ただし、安全性保証が弱いため、Rustの他の仕組みよりも“最後の手段”です。
let x = 10u8;
let y = x as u16; // OK: u8 → u16(安全)
let z = 300u16 as u8; // ⚠️ 256を超えるので「切り詰め」される(z = 44)
つまり as
は「ビット変換」であって、意味的な保証はしません。
👉 **「絶対成功するけど意味は保証しない」**という立ち位置です。
From
/ Into
:安全に変換するペア
🪄 2. From
は「どうやって他の型から作るか」を定義するトレイトです。
Into
はその逆方向に動く**糖衣構文(シンタックスシュガー)**です。
let s = String::from("hello"); // From<&str> for String
let s2: String = "hello".into(); // Into<String> for &str
実際、これらは同義です。
標準ライブラリでは「From
を実装したら自動的にInto
も使える」ようになっています。
💡「常に成功する変換」しか
From
/Into
では扱いません。
TryFrom
/ TryInto
:失敗の可能性がある変換
⚙️ 3. 数値など、全ての変換が安全に行えるとは限らないときに使います。
use std::convert::TryFrom;
let n = u8::try_from(255u16)?; // OK
let m = u8::try_from(300u16); // Err(_) → 失敗!
TryFrom
の戻り値は Result<T, E>
なので、?
演算子で扱えます。
たとえば「文字列→整数」もこれを使っています:
let num = i32::try_from(42u8)?; // OK
let parsed: i32 = "123".parse()?; // 実は `FromStr` トレイトの仕組み(次で説明)
FromStr
:文字列から構造体などを作る
📖 4. これは "123".parse::<i32>()
の裏で動いているトレイトです。
use std::str::FromStr;
let n = i32::from_str("123").unwrap();
let n2: i32 = "123".parse().unwrap(); // 同じ意味!
parse()
は FromStr
のシンタックスシュガー。
TryFrom
のように、戻り値は Result<T, E>
です。
AsRef
/ AsMut
:参照を借りるための変換
🪞 5. AsRef
は「この型を借りて別の参照として見る」ためのトレイト。
汎用的な関数を書くときに使われます。
fn print_path<P: AsRef<std::path::Path>>(path: P) {
println!("{:?}", path.as_ref());
}
print_path("foo/bar.txt"); // &str → Path
print_path(std::path::Path::new("baz.txt")); // Path → Path
つまり AsRef
は「引数の型が違っても、参照を統一的に扱うための仕組み」。
-
From
/Into
… 値の変換 -
AsRef
/AsMut
… 参照の変換
🧠 まとめ:4パターンの使い分け方
目的 | 使うもの | 特徴 |
---|---|---|
プリミティブ変換(整数→浮動小数など) | as |
型安全でないこともある |
常に成功する変換 |
From / Into
|
値の安全な変換 |
失敗するかもしれない変換 |
TryFrom / TryInto
|
Result で返す |
借用(参照)を変換したい |
AsRef / AsMut
|
汎用関数で便利 |
🌱 ちょっとした練習問題(おすすめ)
use std::convert::{From, TryFrom};
use std::str::FromStr;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. as
let x = 42u8 as u16;
// 2. From / Into
let s1 = String::from("hi");
let s2: String = "hi".into();
// 3. TryFrom
let n = u8::try_from(255u16)?;
// let fail = u8::try_from(300u16)?; // Err!
// 4. FromStr
let num = i32::from_str("123")?;
let num2: i32 = "123".parse()?;
// 5. AsRef
fn print_len<T: AsRef<str>>(s: T) {
println!("len = {}", s.as_ref().len());
}
print_len("abc");
print_len(String::from("xyz"));
Ok(())
}