Traits

Инициализация типажа

Типаж нужен для организации интерфейса: он задаёт ограничения-особенности поведения для переменных или структур с неопределёнными (generic) переменными. Мы отделяем объявление типажа от его реализации. При объявлении типажа можно оставить обязательную реализацию на потом, либо вписать реализацию функций в типаже по-умолчанию:

// типаж задаёт метод и ограничения по входным/выходным типам
trait LandVehicle {  
    fn LandDrive(&self) -> String; }  

// типаж задаёт методы плюс их реализация по умолчанию
trait WaterVehicle {  
    fn WaterDrive(&self) { println!("Default float"); }  
}

Применение типажей к структурам данных

Во время применения, если реализация по умолчанию была задана, то можно её переделать под конкретную структуру, либо использовать эту реализацию:

struct Sedan {}  
struct Rocketship {}  

// типаж LandVehicle не имеет реализации по умолчанию, реализуем тут
impl LandVehicle for Sedan {  
    fn LandDrive(&self) -> String { format!("Car zoom-zoom!") } }

// типаж WaterVehicle имеет выше реализацию по умолчанию, используем её
impl WaterVehicle for Rocketship {}

Объединение типажей

При объединении, создаётся ярлык (alias). При этом каждый входящий в него типаж нужно отдельно применить к структуре данных. При этом можно также использовать реализацию определённых в типаже методов по умолчанию, либо написать свою.

// создание ярлыка
trait AmphibiousVehicle: LandVehicle + WaterVehicle {}

// применение типажей к структуре
impl AmphibiousVehicle for Carrier {}  
impl LandVehicle for Carrier {  
    fn LandDrive(&self) -> String { format!("Use air thrust to travel on land") }  
}  
impl WaterVehicle for Carrier {}

Вызов методов экземпляра структуры определённого типажа

fn main() {  
    let toyota_camry = Sedan {};  
    println!("{}",toyota_camry.LandDrive());
  
    let rs = Rocketship {};  
    rs.WaterDrive();  
  
    let project_x = Carrier {};  
    println!("{}",project_x.LandDrive());  
    project_x.WaterDrive();  
}