## trait实现加法抽象
## 数学运算加法
```rust
trait Add<RHS, Output> {
fn add(self, rhs: RHS) -> Output;
}
impl Add<i32, i32> for i32 {
fn add(self, rhs: i32) -> i32 {
self + rhs
}
}
impl Add<u32, i32> for u32 {
fn add(self, rhs: u32) -> i32 {
(self + rhs) as i32
}
}
fn main() {
let (a, b, c, d) = (1i32, 2i32, 3u32, 4u32);
let x: i32 = a.add(b);
let y: i32 = c.add(d);
assert_eq!(x, 3i32);
assert_eq!(y, 7i32);
}
```
## 标准库中的String类型实现Add trait
```rust
pub trait Add<Rhs=Self> {
/// The resulting type after applying the `+` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// Performs the `+` operation.
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
fn add(self, rhs: Rhs) -> Self::Output;
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Add<&str> for String {
type Output = String;
#[inline]
fn add(mut self, other: &str) -> String {
self.push_str(other);
self
}
}
```
```rust
fn main() {
let a = "hello";
let b = " world";
let c = a.to_string() + b;
println!("{:?}", c); // hello world
}
```
> #question 如何识别加号 "+" ? 哪里可以看到具体实现?
## trait一般用法
[learning rust: impl and trait](https://learning-rust.github.io/docs/b5.impls_and_traits.html)
## impl without trait
> struct Player, impl Player , same name without 'for' keyword
```rust
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
> trait only has signature for function, no detail implementation
```rust
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.
```
## Impls, traits & default methods
```rust
struct Player {
first_name: String,
last_name: String,
}
trait FullName {
fn full_name(&self) -> String;
//default method for trait
fn say_hello(&self) {
println!("hello world");
}
}
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());
player_2.say_hello();
}
```
# trait 继承
> pub trait B: A {}
> This is not really inheritance. It’s more like “things that implement B also need to implement A”.
> 并不是真正的继承, 仅仅是一个声明, 意思是实现了B的也需要实现A
```rust
pub trait Animal {
fn howl(&self) { println!("ao ao"); }
}
pub trait Tiger: Animal {
fn find_food(&self) { println!("find food"); }
}
impl<'a> Animal for &'a str {}
impl<'a> Tiger for &'a str {}
fn main(){
"hello".howl();
"hello".find_food(); //find food
}
```
Rust有两个Edition其实并不是一个bad way.
[Rust: A Language for the Next 40 Years - Carol Nichols](https://www.youtube.com/watch?v=A3AdN7U24iU)
![image](https://user-images.githubusercontent.com/150418/57937596-c4f03100-78b5-11e9-8f59-e4388ebd0aaa.png)
> 仅是在High level层面
> 可以交叉使用
![image](https://user-images.githubusercontent.com/150418/57937852-5c558400-78b6-11e9-99ee-ee561f2f1f4d.png)