2016-02-23 2 views
4

Я пытаюсь обернуть голову вокруг объектов цели и как я могу их использовать. Один из сценариев - это возможность передать функцию для обратного вызова, когда выполняется какое-то условие, вызываемое обратным вызовом.Как использовать объекты объектов для обратных вызовов функций?

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); 
} 

Как и в сторону, ваш комментарий

не аргумент аннулируются RET функция

это не совсем верно. У ржавчины нет void «тип», у него есть пустой кортеж, который часто называют единицей типа.

2

Причина, по которой ваш код не работает, заключается в том, что функция run_me и закрытие || println!("Hello World!") не имеют реализаций для вашего обратного вызова. Вы можете исправить это, добавив реализацию Callback для всех типов, реализующих признак Fn():

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 
} 
Смежные вопросы