✅impls常常被用来定义Rust的structs和enums办法
✅ Traits有点儿像OOP语言中的interfaces。它们通常被用来定义必须被提供的功能性。大部分的traits能够为繁多类型实现
然而traits也能够蕴含默认办法实现,在实现类型的时候默认办法能够被重写
1、Impl without traits
struct Player { first_name: String, last_name: String,}impl Player { fn full_name(&self) -> String { format!("{} {}", self.first_name, self.last_name) }}fn main() { let player_1 = Player { first_name: "Rafael".to_string(), last_name: "Nadal".to_string(), }; println!("Player 01: {}", player_1.full_name());}// ⭐️ Implementation must appear in the same crate as the self type// And also in Rust, new traits can be implemented for existing types even for types like i8, f64 and etc.// Same way existing traits can be implemented for new types you are creating.// But we can not implement existing traits into existing types.
Impls & traits,without default methods
struct Player { first_name: String, last_name: String,}trait FullName { fn full_name(&self) -> String;}impl FullName for Player { fn full_name(&self) -> String { format!("{} {}", self.first_name, self.last_name) }}fn main() { let player_2 = Player { first_name: "Roger".to_string(), last_name: "Federer".to_string(), }; println!("Player 02: {}", player_2.full_name());}// Other than functions, traits can contain constants and types.
2、Impls, traits & default methods
trait Foo { fn bar(&self); fn baz(&self) { println!("We called baz."); }}
正如你所看到的办法的第一个参数是非凡的,类型是itself。要么是self,&self要么是 &mut self; self如果它是栈上的值,&self如果它是一个参考,&mut self如果它是一个可变的参考
Impls with Associated functions
一些其余的语言反对静态方法。在这种状况下,咱们能够间接通过class调用一个函数而不是创立一个对象。在Rust中,咱们把它们称为关联函数。咱们在从struct中调用他们的时候应用::而不是.
例如:
Person::new("Elon Musk Jr");
struct Player { first_name: String, last_name: String,}impl Player { fn new(first_name: String, last_name: String) -> Player { Player { first_name : first_name, last_name : last_name, } } fn full_name(&self) -> String { format!("{} {}", self.first_name, self.last_name) }}fn main() { let player_name = Player::new("Serena".to_string(), "Williams".to_string()).full_name(); println!("Player: {}", player_name);}// We have used :: notation for `new()` and . notation for `full_name()`// Also in here, instead of using new() and full_name() separately as two expressions, // we can use Method Chaining. ex. `player.add_points(2).get_point_count();`
3、Traits with generics
trait From<T> { fn from(T) -> Self;} impl From<u8> for u16 { //... } impl From<u8> for u32{ //... } // Should specify after the trait name like generic functions
4、Traits inheritance
trait Person { fn full_name(&self) -> String;} trait Employee : Person { // Employee inherits from person trait fn job_title(&self) -> String; } trait ExpatEmployee : Employee + Expat { // ExpatEmployee inherits from Employee and Expat traits fn additional_tax(&self) -> f64; }
5、Trait objects
当Rust反对动态的发送的时候,它通过一个叫trait objects的办法也反对动静的发送
trait GetSound { fn get_sound(&self) -> String;}struct Cat { sound: String,} impl GetSound for Cat { fn get_sound(&self) -> String { self.sound.clone() } }struct Bell { sound: String,} impl GetSound for Bell { fn get_sound(&self) -> String { self.sound.clone() } }fn make_sound<T: GetSound>(t: &T) { println!("{}!", t.get_sound())}fn main() { let kitty = Cat { sound: "Meow".to_string() }; let the_bell = Bell { sound: "Ding Dong".to_string() }; make_sound(&kitty); // Meow! make_sound(&the_bell); // Ding Dong!}
注:有些特定批示我并没有翻译,但也很简略,能够了解是什么意思