# Rust Trait

Rust trait 是Rust語言的一個特性(性狀)，它描述了它可以提供的每種型別的功能。

`trait`的語法：

``````trait trait_name
//body of the trait.
``````

``````struct Triangle
{
base : f64,
height : f64,
}
trait HasArea
{
fn area(&self)->f64;
}

impl HasArea for Triangle
{
fn area(&self)->f64
{
0.5*(self.base*self.height)
}
}
fn main()
{
let a = Triangle{base:10.5,height:17.4};
let triangle_area = a.area();
println!("Area of a triangle is {}",triangle_area);
}
``````

``````Area of a triangle is 91.35
``````

## 性狀作為引數

``````fn calculate_area(item : impl HasArea)
println!("Area of the triangle is : {}",item.area());
}
``````

## 性狀限制了通用函式

``````fn calculate_area<T>( item : T)
println!(?Area of a triangle is {}?, item.area());
``````

``````fn calculate_area<T : HasArea> (item : T)
{
println!("Area of a triangle is {} ",item.area());
}
``````

``````trait HasArea
{
fn area(&self)->f64;
}
struct Triangle
{
base : f64,
height : f64,
}

impl HasArea for Triangle
{
fn area(&self)->f64
{
0.5*(self.base*self.height)
}
}
struct Square
{
side : f64,
}

impl HasArea for Square
{
fn area(&self)->f64
{
self.side*self.side
}
}
fn calculate_area<T : HasArea>(item : T)
{
println!("Area is : {}",item.area());
}

fn main()
{
let a = Triangle{base:10.5,height:17.4};
let b = Square{side : 4.5};
calculate_area(a);
calculate_area(b);
}
``````

``````Area is : 91.35
Area is : 20.25
``````

## 實施性狀的規則

• 如果範圍中未定義性狀，則無法在任何資料型別上實現該性狀。

``````use::std::fs::File;
fn main()
{
let mut f = File::create("hello.txt");
let str = "Yiibai";
let result = f.write(str);
}
``````

``````error : no method named 'write' found.
let result = f.write(str);
``````

• 正在實現的性狀必須定義。 例如：如果定義`HasArea`性狀，那麼要為`i32`型別實現這個性狀。 但是，無法為型別`i32`實現Rust定義的`toString`性狀，因為型別和性狀沒有在包中定義。

## 多個性狀界限

``````use std::fmt::{Debug, Display};
fn compare_prints<T: Debug + Display>(t: &T)
{
println!("Debug: '{:?}'", t);
println!("Display: '{}'", t);
}

fn main() {
let string = "Yiibai";
compare_prints(&string);
}
``````

``````Debug: ' "Yiibai"'
Display: ' Yiibai'
``````

• 使用出現在括號`{`之前的`where`子句來編寫系結。
• `where`子句也可以應用於任意型別。
• 當使用`where`子句時，它使語法比普通語法更具表現力。

``````fn fun<T: Display+Debug, V: Clone+Debug>(t:T,v:V)->i32
//block of code;
``````

``````fn fun<T, V>(t:T, v:V)->i32
where T : Display+ Debug,
V : Clone+ Debug

//block of code;
``````

``````trait Perimeter
{
fn a(&self)->f64;
}
struct Square
{
side : f64,
}
impl Perimeter for Square
{
fn a(&self)->f64
{
4.0*self.side
}
}
struct Rectangle
{
length : f64,
}
impl Perimeter for Rectangle

{
fn a(&self)->f64
{
}
}
fn print_perimeter<Square,Rectangle>(s:Square,r:Rectangle)
where Square : Perimeter,
Rectangle : Perimeter
{
let r1 = s.a();
let r2 = r.a();
println!("Perimeter of a square is {}",r1);
println!("Perimeter of a rectangle is {}",r2);
}
fn main()
{
let sq = Square{side : 6.2};
let rect = Rectangle{length : 3.2,breadth:5.6};
print_perimeter(sq,rect);
}
``````

``````Perimeter of a square is 24.8
Perimeter of a rectangle is 17.6
``````

## 預設方法

``````trait Sample

fn a(&self);
fn b(&self)
{
println!("Print b");
}
``````

``````trait Sample
{
fn a(&self);
fn b(&self)
{
println!("Print b");
}
}

struct Example
{
a:i32,
b:i32,
}

impl Sample for Example
{
fn a(&self)
{
println!("Value of a is {}",self.a);
}

fn b(&self)
{
println!("Value of b is {}",self.b);
}
}
fn main()
{
let r = Example{a:5,b:7};
r.a();
r.b();
}
``````

``````Value of a is : 5
Value of b is : 7
``````

## 繼承

``````trait B : A;
``````

``````trait A
{
fn f(&self);
}
trait B : A
{
fn t(&self);
}
struct Example
{
first : String,
second : String,
}
impl A for Example
{
fn f(&self)
{

print!("{} ",self.first);
}

}
impl B for Example
{
fn t(&self)
{
print!("{}",self.second);
}
}
fn main()
{
let s = Example{first:String::from("Yiibai"),second:String::from("tutorial")};
s.f();
s.t();
}
``````

``````Yiibai tutorial
``````