let elem = 5u8;
// Создадим пустой вектор (расширяемый массив).
let mut vec = Vec::new();
// В данном месте компилятор не знает точный тип `vec`, он лишь знает,
// что это вектор чего-то там (`Vec<_>`).
// Добавляем `elem` в вектор.
vec.push(elem);
// Ага! Теперь компилятор знает, что `vec` - это вектор, который хранит в себе тип `u8`
// (`Vec<u8>`)
// ЗАДАНИЕ ^ Попробуйте закомментировать строку `vec.push(elem)`
println!("{:?}", vec);
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Не потребовалось никакой аннотации типов переменных, компилятор счастлив, как и программист!
Оператор type используется, чтобы задать новое имя существующему типу. Имя типа должно быть в стиле UpperCamelCase, иначе компилятор выдаст предупреждение. Исключением являются примитивные типы: usize, f32 и другие.
// `NanoSecond` это новое имя для `u64`.
type NanoSecond = u64;
type Inch = u64;
// Используйте этот атрибут, чтобы не выводить предупреждение
// о именах не в стиле CamelCase
#[allow(non_camel_case_types)]
type u64_t = u64;
// ЗАДАНИЕ ^ Попробуйте удалить атрибут
fn main() {
// `NanoSecond` = `Inch` = `u64_t` = `u64`.
let nanoseconds: NanoSecond = 5 as u64_t;
let inches: Inch = 2 as u64_t;
// Обратите внимание, что псевдонимы *не предоставляют* никакой
// дополнительной безопасности типов, так как *не являются* новыми типами
println!("{} nanoseconds + {} inches = {} unit?",
nanoseconds,
inches,
nanoseconds + inches);
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Основное применение псевдонимов — сокращение размера кода: например, тип IoResult<T> является псевдонимом типа Result<T, IoError>.
Атрибуты
Примитивные типы могут быть сконвертированы в другие при помощи приведения типов.
Rust предоставляет преобразование между пользовательскими типами (такими как, struct и enum) через использование трейтов. Общие преобразования используют трейты From и Into. Однако есть и конкретные трейты для более частных случаев, например для конвертации String.
Типажи From и Into связаны по своей сути, и это стало частью их реализации. Если вы можете конвертировать тип А в тип В, то будет легко предположить, что мы должны быть в состоянии конвертировать тип В в тип А.
Типаж From позволяет типу определить, как он будет создаваться из другого типа, что предоставляет очень простой механизм конвертации между несколькими типами. Есть несколько реализаций этот типажа в стандартной библиотеке для преобразования примитивов и общих типов.
Для примера, мы можем легко конвертировать str в String
#![allow(unused)]
fn main() {
let my_str = "привет";
let my_string = String::from(my_str);
}
Мы можем сделать нечто похожее для определения конвертации для нашего собственного типа.
use std::convert::From;
#[derive(Debug)]
struct Number {
value: i32,
}
impl From<i32> for Number {
fn from(item: i32) -> Self {
Number { value: item }
}
}
fn main() {