2016-02-23 78 views
4

我想把頭圍繞特質對象,以及如何使用它們。一種情況是我可能想要爲回調傳遞一個函數,當滿足某個條件時會調用回調函數。如何使用trait對象進行函數回調?

fn bind_callback(key: u64, /* pass function */) { 
    // when key is matched with the event, call the function 
} 

我該怎麼做?我聽說我可以使用特質對象來實現這個目標,但是我會如何去實現這個目標呢?有人能給我看一個例子嗎?下面是我在什麼:

trait Callback { 
    fn callback(self); 
} 

fn pass_callback(f: &Callback) { 
    f.callback(); 
} 

fn run_me() { 
    println!("Hello World!"); 
} 

fn main() { 
    pass_callback(&run_me); // run simple no arg void ret function 
    pass_callback(|| println!("Hello World!")); // same thing 
} 

我知道這是極其錯誤的,我想明白,我怎麼會做到這樣的事情。我的錯誤輸出是:

<anon>:14:19: 14:26 error: the trait `Callback` is not implemented for the type `fn() {run_me}` [E0277] 
<anon>:14  pass_callback(&run_me); 
          ^~~~~~~ 
<anon>:14:19: 14:26 help: see the detailed explanation for E0277 
<anon>:14:19: 14:26 note: required for the cast to the object type `Callback` 
<anon>:15:19: 15:46 error: mismatched types: 
expected `&Callback`, 
    found `[[email protected]<anon>:15:19: 15:46]` 
(expected &-ptr, 
    found closure) [E0308] 
<anon>:15  pass_callback(|| println!("Hello World!")); 
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~ 
<anon>:15:19: 15:46 help: see the detailed explanation for E0308 
error: aborting due to 2 previous errors 
playpen: application terminated with error code 101 

回答

6

如果要使用閉包和函數作爲參數,則不能使用自己的特徵。相反,您使用Fn*系列之一:

fn pass_callback<F>(f: F) 
    where F: Fn() 
{ 
    f(); 
} 

fn run_me() { 
    println!("Hello World!"); 
} 

fn main() { 
    pass_callback(run_me); 
    pass_callback(|| println!("Hello World!")); 
} 

如果你真的想使用自己的特點,你可以,但是你需要在某物上實現這個特性,並將這個物品傳遞給你功能:

trait Callback { 
    fn callback(&self, value: u8) -> bool; 
} 

struct IsEven; 
impl Callback for IsEven { 
    fn callback(&self, value: u8) -> bool { 
     value % 2 == 0 
    } 
} 

fn pass_callback<C>(f: C) 
    where C: Callback 
{ 
    if f.callback(42) { 
     println!("Callback passed"); 
    } 
} 

fn main() { 
    pass_callback(IsEven); 
} 

順便說一句,您的評論

沒有ARG無效RET功能

並不完全正確。 Rust沒有void「類型」,它具有空元組,通常稱爲單元類型

2

你的代碼不起作用的原因是函數run_me和關閉|| println!("Hello World!")沒有你的回調特徵的實現。您可以通過爲所有類型實施Fn()特徵添加Callback實現來解決此問題:

trait Callback { 
    fn callback(&self); 
} 

fn pass_callback(f: &Callback) { 
    f.callback(); 
} 

fn run_me() { 
    println!("Hello World!"); 
} 

// For every type T that implements Fn(), 
// this is the Callback implementation. 
impl<T: Fn()> Callback for T { 
    fn callback(&self) { 
     self() 
    } 
} 

fn main() { 
    pass_callback(&run_me); // a simple function 
    pass_callback(&|| println!("Hello World!")); // a closure 
}