Rust From and Into traits / Rust From 与 Into Trait
What you’ll learn / 你将学到: Rust’s type conversion traits —
From<T>andInto<T>for infallible conversions,TryFromandTryIntofor fallible ones. ImplementFromand getIntofor free. Replaces C++ conversion operators and constructors.Rust 的类型转换 trait —— 用于无误转换的
From<T>和Into<T>,以及用于可能失败转换的TryFrom和TryInto。实现From即可免费获得Into。取代了 C++ 的转换运算符和构造函数。
FromandIntoare complementary traits to facilitate type conversion
-
From和Into是互补的 trait,旨在简化类型转换。
-
- Types normally implement on the
Fromtrait. theString::from()converts from “&str” toString, and compiler can automatically derive&str.into
- Types normally implement on the
-
- 类型通常实现
Fromtrait。比如String::from()将 “&str” 转换为String,编译器可以自动根据此推导出&str.into的实现。
- 类型通常实现
struct Point {x: u32, y: u32}
-// Construct a Point from a tuple
+// Construct a Point from a tuple / 从元组构造 Point
impl From<(u32, u32)> for Point {
fn from(xy : (u32, u32)) -> Self {
- Point {x : xy.0, y: xy.1} // Construct Point using the tuple elements
+ Point {x : xy.0, y: xy.1} // Using elements / 使用元组元素构造 Point
}
}
fn main() {
let s = String::from("Rust");
let x = u32::from(true);
let p = Point::from((40, 42));
- // let p : Point = (40.42)::into(); // Alternate form of the above
+ // let p : Point = (40.42)::into(); // Alternate form / 上述形式的另一种写法
println!("s: {s} x:{x} p.x:{} p.y {}", p.x, p.y);
}
-
- Implement a
Fromtrait forPointto convert into a type calledTransposePoint.TransposePointswaps thexandyelements ofPoint
- Implement a
-
- 为
Point实现Fromtrait,将其转换为名为TransposePoint的类型。TransposePoint会交换Point的x和y元素。
- 为
Solution (click to expand)
Solution (click to expand) / 解决方案(点击展开)
struct Point { x: u32, y: u32 }
struct TransposePoint { x: u32, y: u32 }
impl From<Point> for TransposePoint {
fn from(p: Point) -> Self {
TransposePoint { x: p.y, y: p.x }
}
}
fn main() {
let p = Point { x: 10, y: 20 };
let tp = TransposePoint::from(p);
- println!("Transposed: x={}, y={}", tp.x, tp.y); // x=20, y=10
+ println!("Transposed: x={}, y={}", tp.x, tp.y); // 结果:x=20, y=10
- // Using .into() — works automatically when From is implemented
+ // Using .into() — works automatically / 使用 .into() —— 在实现 From 后自动起效
let p2 = Point { x: 3, y: 7 };
let tp2: TransposePoint = p2.into();
- println!("Transposed: x={}, y={}", tp2.x, tp2.y); // x=7, y=3
+ println!("Transposed: x={}, y={}", tp2.x, tp2.y); // 结果:x=7, y=3
}
- // Output:
+ // Output / 输出:
// Transposed: x=20, y=10
// Transposed: x=7, y=3
-
Defaultcan be used to implement default values for a type
-
Default可用于为类型实现默认值。
-
- Types can use the ```Derive``` macro with ```Default``` or provide a custom implementation
-
- 类型可以使用 ```Derive``` 宏自动派生 ```Default```,也可以提供自定义实现。
#[derive(Default, Debug)]
struct Point {x: u32, y: u32}
#[derive(Debug)]
struct CustomPoint {x: u32, y: u32}
impl Default for CustomPoint {
fn default() -> Self {
CustomPoint {x: 42, y: 42}
}
}
fn main() {
- let x = Point::default(); // Creates a Point{0, 0}
+ let x = Point::default(); // Creates / 创建一个 Point{0, 0}
println!("{x:?}");
let y = CustomPoint::default();
println!("{y:?}");
}
-
Defaulttrait has several use cases including
-
Defaulttrait 具有多种用例,包括:
-
- Performing a partial copy and using default initialization for rest
-
- 执行部分复制,并对其余部分使用默认初始化。
-
- Default alternative for ```Option``` types in methods like ```unwrap_or_default()```
-
- 作为 ```Option``` 类型的默认备选项,例如在 ```unwrap_or_default()``` 方法中。
#[derive(Debug)]
struct CustomPoint {x: u32, y: u32}
impl Default for CustomPoint {
fn default() -> Self {
CustomPoint {x: 42, y: 42}
}
}
fn main() {
let x = CustomPoint::default();
- // Override y, but leave rest of elements as the default
+ // Override y, but leave rest default / 覆盖 y,但其余元素保留为默认值
let y = CustomPoint {y: 43, ..CustomPoint::default()};
println!("{x:?} {y:?}");
let z : Option<CustomPoint> = None;
- // Try changing the unwrap_or_default() to unwrap()
+ // Try changing unwrap_or_default() to unwrap() / 尝试将 unwrap_or_default() 更改为 unwrap()
println!("{:?}", z.unwrap_or_default());
}
-
- Rust doesn’t support implicit type conversions and
ascan be used forexplicitconversions
- Rust doesn’t support implicit type conversions and
-
- Rust 不支持隐式类型转换,可以使用
as进行显式转换。
- Rust 不支持隐式类型转换,可以使用
-
asshould be sparingly used because it’s subject to loss of data by narrowing and so forth. In general, it’s preferable to useinto()orfrom()where possible
-
- 应当谨慎使用
as,因为它可能会导致由于范围收窄(narrowing)等原因产生的数据丢失。通常情况下,尽可能使用into()或from()更好。
- 应当谨慎使用
fn main() {
let f = 42u8;
- // let g : u32 = f; // Will not compile
+ // let g : u32 = f; // Will not compile / 无法编译
- let g = f as u32; // Ok, but not preferred. Subject to rules around narrowing
+ let g = f as u32; // Ok, but not preferred / 可以使用但不推荐。受收窄规则限制
- let g : u32 = f.into(); // Most preferred form; infallible and checked by the compiler
+ let g : u32 = f.into(); // Most preferred / 最推荐的形式;无误且由编译器检查
- //let k : u8 = f.into(); // Fails to compile; narrowing can result in loss of data
+ //let k : u8 = f.into(); // Fails to compile / 编译失败;收窄可能导致数据丢失
- // Attempting a narrowing operation requires use of try_into
+ // Narrowing requires try_into / 尝试收窄操作需要使用 try_into
if let Ok(k) = TryInto::<u8>::try_into(g) {
println!("{k}");
}
}