rust trait設計精神是資料
、行為定義
、行為實作
,而java interface是資料 + 行為實作
、行為定義
,使得產生以下差異:
rust trait將method與資料分離,但java interface沒有分離,這會導致行為實作與資料耦合
java interface得修改其他人的lib
// 此資料在其他人的lib class TwoInterfaces { } // ------- // 如果想定義一個interface規範TwoInterfaces,一定得去改其他人的lib interface Bar { int someMethod(); }
rust trait可直接改自己的code
// 此資料在其他lib struct Struct; // ------- // 如果想定義一個trait規範Struct,直接在自己的code裡面規範即可 trait Trait<T> { fn method(&self) -> T; } impl Trait<u8> for Struct { fn method(&self) -> u8 { 16 } } impl Trait<String> for Struct { fn method(&self) -> String { "hello".to_string() } } fn main() { let s = Struct; let a: u8 = s.method(); let b: String = s.method(); println!("a={}, b={}", a, b); }
trait可以實作相同名稱但行為不同的method
java interface不能這樣做
// 行為綁定在資料上 class TwoGenerics implements Foo<Integer>, Foo<String> { public void someMethod(??? value) {} // Can't implement, must be one method } interface Foo<T> { void someMethod(T value); }
rust trait可以這樣做
struct Struct; trait Trait<T> { fn method(&self) -> T; } impl Trait<u8> for Struct { fn method(&self) -> u8 { 16 } } impl Trait<String> for Struct { fn method(&self) -> String { "hello".to_string() } } fn main() { let s = Struct; // 因為行為沒有綁定在資料上,而是在呼叫時說明需要哪個行為 let a: u8 = s.method(); let b: String = s.method(); println!("a={}, b={}", a, b); }