Учебники

Rust — Общие типы

Обобщения являются средством для написания кода для нескольких контекстов с различными типами. В Rust дженерики относятся к параметризации типов данных и признаков. Обобщения позволяют писать более сжатый и чистый код, уменьшая дублирование кода и обеспечивая безопасность типов. Концепция Generics может применяться к методам, функциям, структурам, перечислениям, коллекциям и признакам.

Синтаксис <T>, известный как параметр типа, используется для объявления универсальной конструкции. T представляет любой тип данных.

Иллюстрация: Общая коллекция

В следующем примере объявляется вектор, который может хранить только целые числа.

fn main(){
   let mut vector_integer: Vec<i32> = vec![20,30];
   vector_integer.push(40);
   println!("{:?}",vector_integer);
}

Выход

[20, 30, 40]

Рассмотрим следующий фрагмент —

fn main() {
   let mut vector_integer: Vec<i32> = vec![20,30];
   vector_integer.push(40);
   vector_integer.push("hello"); 
   //error[E0308]: mismatched types
   println!("{:?}",vector_integer);
}

Приведенный выше пример показывает, что вектор целочисленного типа может хранить только целочисленные значения. Итак, если мы попытаемся вставить строковое значение в коллекцию, компилятор вернет ошибку. Дженерики делают коллекции более безопасными.

Иллюстрация: Общая структура

Параметр type представляет тип, который компилятор заполнит позже.

struct Data<T> {
   value:T,
}
fn main() {
   //generic type of i32
   let t:Data<i32> = Data{value:350};
   println!("value is :{} ",t.value);
   //generic type of String
   let t2:Data<String> = Data{value:"Tom".to_string()};
   println!("value is :{} ",t2.value);
}

В приведенном выше примере объявляется общая структура с именем Data . Тип <T> указывает некоторый тип данных. Функция main () создает два экземпляра — целочисленный и строковый экземпляр структуры.

Выход

value is :350
value is :Tom

Черты

Черты могут быть использованы для реализации стандартного набора поведений (методов) в нескольких структурах. Черты подобны интерфейсам в объектно-ориентированном программировании. Синтаксис черты, как показано ниже —

Объявить черту

trait some_trait {
   //abstract or method which is empty
   fn method1(&self);
   // this is already implemented , this is free
   fn method2(&self){
      //some contents of method2
   }
}

Черты могут содержать конкретные методы (методы с телом) или абстрактные методы (методы без тела). Используйте конкретный метод, если определение метода будет общим для всех структур, реализующих черту. Однако структура может переопределить функцию, определенную признаком.

Используйте абстрактные методы, если определение метода варьируется для реализующих структур.

Синтаксис — реализовать черту

impl some_trait for structure_name {
   // implement method1() there..
   fn method1(&self ){
   }
}

В следующих примерах определяется черта Printable с помощью метода print () , который реализуется структурной книгой .

fn main(){
   //create an instance of the structure
   let b1 = Book {
      id:1001,
      name:"Rust in Action"
   };
   b1.print();
}
//declare a structure
struct Book {
   name:&'static str,
   id:u32
}
//declare a trait
trait Printable {
   fn print(&self);
}
//implement the trait
impl Printable for Book {
   fn print(&self){
      println!("Printing book with id:{} and name {}",self.id,self.name)
   }
}

Выход

Printing book with id:1001 and name Rust in Action

Общие функции

В примере определяется универсальная функция, которая отображает переданный ей параметр. Параметр может быть любого типа. Тип параметра должен реализовывать черту Display, чтобы его значение могло быть напечатано println! макро.