|
|
|
@ -19,7 +19,7 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
解决办法很简单,只要把 `b` 转换成 `i32` 类型即可,Rust中内置了一些基本类型之间的转换,这里使用 `as` 操作符来完成:`if a < (b as i32) {...}`。那么为什么不把 `a` 转换成 `u16` 类型呢?
|
|
|
|
|
|
|
|
|
|
因为每个类型能表达的范围不一样,如果把大的类型转换成小的类型,会造成错误,因此我们需要把小的类型转换成大的类型,来避免这些问题的发生。
|
|
|
|
|
因为每个类型能表达的数据范围不同,如果把范围较大的类型转换成较小的类型,会造成错误,因此我们需要把范围较小的类型转换成较大的类型,来避免这些问题的发生。
|
|
|
|
|
|
|
|
|
|
> 使用类型转换需要小心,因为如果执行以下操作 `300_i32 as i8`,你将获得 `44` 这个值,而不是 `300`,因为 `i8` 类型能表达的的最大值为 `2^7 - 1`,使用以下代码可以查看 `i8` 的最大值:
|
|
|
|
|
```rust
|
|
|
|
@ -65,7 +65,7 @@ fn main() {
|
|
|
|
|
就算 `e as U1 as U2` 是合法的,也不能说明 `e as U2` 是合法的(`e` 不能直接转换成 `U2`)。
|
|
|
|
|
|
|
|
|
|
## TryInto转换
|
|
|
|
|
在一些场景中,使用 as` 关键字会有比较大的限制,如果你想要在类型转换上拥有完全的控制而不依赖内置的转换,例如处理转换错误,那么你将需要 `TryInto`:
|
|
|
|
|
在一些场景中,使用 `as` 关键字会有比较大的限制。如果你想要在类型转换上拥有完全的控制而不依赖内置的转换,例如处理转换错误,那么可以使用 `TryInto`:
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
use std::convert::TryInto;
|
|
|
|
@ -125,7 +125,7 @@ fn reinterpret(foo: Foo) -> Bar {
|
|
|
|
|
简单粗暴,但是从另外一个角度来看,也挺啰嗦的,好在Rust为我们提供了更通用的方式来完成这个目的。
|
|
|
|
|
|
|
|
|
|
#### 强制类型转换
|
|
|
|
|
在某些情况下,类型是可以进行隐式强制转换的,这些转换弱化了 Rust 的类型系统,它们的存在是为了让Rust在大多数场景可以工作(说白了,帮助用户省事),而不是报各种类型上的编译错误。
|
|
|
|
|
在某些情况下,类型是可以进行隐式强制转换的,虽然这些转换弱化了 Rust 的类型系统,但是它们的存在是为了让Rust在大多数场景可以工作(说白了,帮助用户省事),而不是报各种类型上的编译错误。
|
|
|
|
|
|
|
|
|
|
首先,在匹配特征时,不会做任何强制转换(除了方法)。一个类型 `T` 可以强制转换为 `U`,不代表 `impl T` 可以强制转换为 `impl U`,例如下面的代码就无法通过编译检查:
|
|
|
|
|
```rust
|
|
|
|
@ -163,7 +163,7 @@ error[E0277]: the trait bound `&mut i32: Trait` is not satisfied
|
|
|
|
|
|
|
|
|
|
再进一步,我们使用[完全限定语法](https://course.rs/basic/trait/advance-trait.html#完全限定语法)来进行准确的函数调用:
|
|
|
|
|
1. 首先,编译器检查它是否可以直接调用`T::foo(value)`,称之为**值方法调用**
|
|
|
|
|
2. 如果上一步调用无法完成(例如方法类型错误或者特征没有针对`Self`进行实现,上文提到过特征不能进行强制转换),那么编译器会尝试增加自动引用,以为着编译器会尝试以下调用:`<&T>::foo(value)`和`<&mut T>::foo(value)`,称之为**引用方法调用**
|
|
|
|
|
2. 如果上一步调用无法完成(例如方法类型错误或者特征没有针对 `Self` 进行实现,上文提到过特征不能进行强制转换),那么编译器会尝试增加自动引用,以为着编译器会尝试以下调用:`<&T>::foo(value)`和`<&mut T>::foo(value)`,称之为**引用方法调用**
|
|
|
|
|
3. 若上面两个方法依然不工作,编译器会试着解引用`T`,然后再进行尝试。这里使用了`Deref`特征 - 若`T: Deref<Target = U>`(`T`可以被解引用为`U`),那么编译器会使用`U`类型进行尝试,称之为**解引用方法调用**
|
|
|
|
|
4. 若`T`不能被解引用,且`T`是一个定长类型(在编译器类型长度是已知的),那么编译器也会尝试将`T`从定长类型转为不定长类型,例如将`[i32; 2]`转为`[i32]`
|
|
|
|
|
5. 若还是不行,那...没有那了,最后编译器大喊一声:汝欺我甚,不干了!
|
|
|
|
|