// Anyone with the "Flying" badge must have a method called fly
traitFlying{fnfly(&self);// Takes a reference to itself, returns nothing
}// Trait implementation
// Our hero
structSuperHero{name: String,}// Our enemy
structWickedWitch{name: String,}// We give both the Flying badge, but they implement it differently
implFlyingforSuperHero{fnfly(&self){println!("{} soars through the sky majestically!",self.name);}}implFlyingforWickedWitch{fnfly(&self){println!("{} cackles loudly as her broomstick rattles into the air!",self.name);}}// ONE function, that works on ANYTHING with the Flying badge:
// This function doesn't care if it's a hero or a witch.
// It just says: "Bring me anything with the 'Flying' badge."
fnrace_to_the_castle(flyer: &implFlying){println!("The race starts!");flyer.fly();// We know it can fly, because it has the badge!
println!("We made it to the castle!");}fnmain(){lethero=SuperHero{name: String::from("Captain Soar")};letwitch=WickedWitch{name: String::from("Elvira")};// Both work perfectly!
race_to_the_castle(&hero);race_to_the_castle(&witch);}
Turbofish
При этом можно написать функцию race_to_the_castle двумя способами:
// короткий способ, использовался ранее:
fnrace_to_the_castle(flyer: &implFlying){flyer.fly();}// Способ turbofish way (полный generic syntax):
fnrace_to_the_castle<F: Flying>(flyer: &F){flyer.fly();}
Короткий способ подходит для простых случаев, но ломается на сложных. Примеры, когда нужно переходить на turbofish:
Несколько параметров должны быть ОДИНАКОВОГО типа
Нужны два животных для битвы, и они обязаны быть одинакового типа:
// SHORTHAND: This allows a Cat and a Dog to be shuffled around
fnshuffle_pair(a: &implAnimal,b: &implAnimal){// 'a' could be a Cat, 'b' could be a Dog
}// TURBOFISH: This FORCES both to be the same type
fnshuffle_pair<T: Animal>(a: &T,b: &T){// a and b MUST be the same kind of animal
}fnmain(){letcat=Cat{name: String::from("Whiskers")};letdog=Dog{name: String::from("Rover")};// Works with shorthand (different types allowed)
shuffle_pair(&cat,&dog);// OK
// ERROR with turbofish (cat and dog are different types!)
// shuffle_pair::<Cat>(&cat, &dog); // 💥 Dog ≠ Cat
}
Тип данных на выходе равен типу на входе
// You put in a specific animal, you get THAT same type back
fnclone_animal<A: Animal+Clone>(original: &A)-> A{original.clone()// Returns the same type that went in
}fnmain(){letcat=Cat{name: String::from("Whiskers")};letcloned_cat=clone_animal(&cat);// We know cloned_cat is a Cat
}
Нужно НЕСКОЛЬКО типажей одновременно
// This thing must be Flying AND have a BattleCry
fndramatic_entrance<F: Flying+BattleCry>(fighter: &F){fighter.battle_cry();fighter.fly();}