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();
}