Продолжаю сравнивать трейты в
Rust и протоколы в
Swift. Столкнулся с интересным ограничением в
Rust!
В
Swift мы можем возвращать разные типы, реализующие протокол:
protocol Vehicle {
func drive()
}
struct Car: Vehicle {
func drive() {
print("Едем на машине")
}
}
struct Bike: Vehicle {
func drive() {
print("Едем на велосипеде")
}
}
func getVehicle(isCar: Bool) -> Vehicle {
if isCar {
Car()
} else {
Bike()
}
}
// Использование
let vehicle = getVehicle(isCar: true)
vehicle.drive() // Едем на машине
Но в
Rust при использовании трейтов так реализовать не получится:
trait Vehicle {
fn drive(&self);
}
struct Car;
struct Bike;
impl Vehicle for Car {
fn drive(&self) {
println!("Едем на машине");
}
}
impl Vehicle for Bike {
fn drive(&self) {
println!("Едем на велосипеде");
}
}
fn get_vehicle(is_car: bool) -> impl Vehicle {
if is_car {
Car
} else {
Bike // Ошибка: if and else have incompatible types
}
}
// Использование
let vehicle = get_vehicle(true);
vehicle.drive();
Rust требует, чтобы все варианты условия возвращали один и тот же тип. Это ограничение безопасности, но иногда неудобно на практике.
Swift с протоколами в этом плане работает более дружелюбно.