Rust 中的 Trait 是 Rust 語言的乙個特性,它描述了它可以提供的每種型別的功能。 它類似於其他語言中定義的介面的特徵,例如 j**a go c++ 的介面。 功能是對方法簽名進行分組以定義一組行為的方法。 特徵是使用trait關鍵字。
100 幫助計畫
語法:特徵是通過 trait 關鍵字宣告的(統稱為介面或行為)。 在大括號內,宣告了乙個方法簽名,用於描述實現介面的型別的行為。
trait
fn main()
let a = **
let **area = a.area();
println!("三角形的面積為:{}",**area);
在上面的示例中,宣告了乙個名為 hasarea 的功能,其中包含 area() 函式的宣告。 hasarea 是在 ** 型別上實現的。 通過使用 struct 例項(即area()) 來簡單地呼叫 area() 函式。
介面作為引數
介面還可以用作許多不同型別的引數。
上面的示例實現了 hasarea 功能,並包含 area() 函式的定義。 我們可以定義呼叫 area() 函式的 calculate area() 函式,並使用實現 hasarea 功能的型別的例項來呼叫 area() 函式。
示例:fn calculate area(item : impl hasarea)。
println!(“三角形的面積為:{}item.”)area())
泛型介面函式的邊界
介面非常有用,因為它們描述了不同方法的行為。 但是,泛型函式不遵循此約束。 讓我們通過乙個簡單的場景來理解這一點:
fn calculate_area( item : t)
println!(?area of a **is {}item.area())
在上述情況下,Rust 編譯器丟擲乙個“錯誤,沒有找到名為 t 型別的方法”。 如果我們將該功能繫結到泛型 t,我們可以解決以下錯誤:
fn calculate_area (item : t)
println!("area of a **is {}",item.area())
在上面的例子中,這意味著“t 可以是實現 hasarea 功能的任何型別”。 rust 編譯器知道任何實現 hasarea 特性的型別都會有乙個 area() 函式。
讓我們看乙個簡單的例子:
trait hasarea
fn area(&self)->f64;
struct **
base : f64,
height : f64,
impl hasarea for **
fn area(&self)->f64
struct square
side : f64,
impl hasarea for square
fn area(&self)->f64
fn calculate_area(item : t)
println!("area is : ",item.area())
fn main()
let a = **
let b = square;
calculate_area(a);
calculate_area(b);
輸出可以自己執行,在上面的示例中,calculate area() 函式是 “t” 上的通用函式。
Rust 實現了介面的規則
實現特徵有兩個限制:
如果未在作用域中定義該功能,則無法在任何資料型別上實現該功能。
我們正在實施的特徵必須由我們來定義。
使用“+”操作。
使用 where 條件。
可以使用 where 條件編寫邊界。 出現在左括號之前的語句。
where 子句也可以應用於任何型別。
何時何地使用 where 子句,它使語法比普通語法更具表現力。
下面是一些示例來說明每個功能規則:
use::std::fs::file;
fn main()
let mut f = file::create("hello.txt");
let str = "j**atpoint";
let result = f.write(str);
在上述情況下,Rust 編譯器丟擲乙個錯誤,指出“沒有名為'write'的方法;發現“ASuse::std::fs::file;命名空間不包含 write() 方法。 因此,我們需要:使用寫入功能消除編譯錯誤
如果我們定義hasarea介面,那麼我們可以為 i32 型別實現這個介面。 但是,我們無法實現 Rust 為 i32 型別定義的內容tostring介面行為,因為它未在我們的型別和介面中定義tostring
如果我們想繫結多個屬性,我們可以使用 + 運算子,如下例所示:
use std::fmt::;
fn compare_prints(t: &t) ,t);
println!("display: '{}'", t);
fn main()
在上面的例子中,通過使用 + 操作,實現了 debug 和 display 這兩個介面,並繫結了 t 型別
預設方法
如果已定義方法,則可以將預設方法新增到特徵定義中。
trait sample
fn a(&self);
fn b(&self)
在上述情況下,預設方法將新增到介面定義中。 我們還可以覆蓋預設方法。
方案示例。 trait sample
fn a(&self);
fn b(&self)
struct example
a:i32,b:i32,impl sample for example
fn a(&self),self.a);
fn b(&self),self.b);
fn main()
let r = example;
r.a();
r.b();
在上面的示例中,b() 函式的行為在 trait 中定義並被覆蓋。 因此,我們可以得出結論,我們可以重寫 trait 中定義的方法。
遺產
從另乙個介面派生的介面方法稱為遺產。有時,需要實現乙個需要實現另乙個介面的方法。 如果我們想從“A”介面派生出“B”介面,那麼從另乙個介面派生的介面稱為繼承。 有時,需要實現乙個需要實現另乙個介面的方法。 如果我們想從“A”介面匯出“B”介面,會寫成如下:
trait b : a;
示例:性狀 A
fn f(&self);
trait b : a
fn t(&self);
struct example
first : string,second : string,impl a for example
fn f(&self),self.first);
impl b for example,self.second);
fn main()
let s = example;
s.f();
s.t();
在上面的示例中,我們實現了“b”功能。 因此,它還需要實現“a”功能。 如果我們沒有實現 “A” 功能,那麼 Rust 編譯器將丟擲錯誤。