Chắc hẳn đã nhiều lần, khi lập trình, chúng ta cần đến các thao tác chuyển đổi kiểu dữ liệu, chuyển kiểu dữ liệu từ kiểu Type_A
sang kiểu Type_B
với Type_A
và Type_B
là các kiểu dữ liệu bất kỳ. Trong Rust, việc chuyển đổi kiểu dữ liệu của một giá trị kiểu số cơ bản được thực hiện một cách dễ dàng thông qua lệnh as
, ví dụ:
fn main() { let n1: i8 = 127; // 0111 1111 let n2: i16 = n1 as i16; // 0000 0000 0111 1111 println!("n1: {0:08b} ({0}) -> n2: {1:016b} ({1})", n1, n2); let n3: i16 = 128; // 0000 0000 1000 0000 let n4: i8 = n3 as i8; // 1000 0000 println!("n3: {0:016b} ({0}) -> n4: {1:08b} ({1})", n3, n4);
}
Khi chạy mã nguồn 01 sẽ cho kết quả như dưới đây: (Rust Playground)
n1: 01111111 (127) -> n2: 0000000001111111 (127)
n3: 0000000010000000 (128) -> n4: 10000000 (-128)
Như chúng ta thấy Rust đã tự động chuyển đổi kiểu dữ liệu cho chúng ta mà về cơ bản là cắt bỏ đi các bit giá trị cao (MSB) thừa khi chuyển đổi từ một kiểu dữ liệu lớn sang môt kiểu dữ liệu nhỏ hơn. Còn trong tình huóng chuyển đổi từ một kiểu dữ liệu nhỏ sang một kiểu dữ liệu lớn thì thêm các bit 0
giá trị cao cần thiết cho đủ kích thước số bit.
Đối với các kiểu dữ liệu số cơ bản (i8
, i16
, u8
, u16
, boolean
, v.v.) thì trong Rust ta chỉ cần sử dụng lệnh as
như trong ví dụ trên.
Tuy nhiên, trong thực tế, sẽ nhiều lúc chúng ta cần chuyển đổi các kiểu dữ liệu, các cấu trúc dữ liệu do chúng ta tự định nghĩa và phức hơn thì không thể dùng as
. Với những bài toán này, Rust cung cấp cho chúng ta các cặp thuộc tính hành vi (”trait”) Into
/From
và TryInto
/TryFrom
để có thể phát triển mở rộng khả năng chuyển đổi qua lại các kiểu dữ liệu bất kỳ.
Anh em hãy xem video “#27 Into/TryInto vs From/TryFrom - Ý nghĩa và cách dùng” trên kênh RustDEV Vietnam để hiểu rõ hơn về cách sử dụng cũng như khả năng của các thuộc tính hành vi này nhé!