从默认特征方法返回Self的TypeId

时间:2020-09-27 14:40:12

标签: rust traits

我正在实现自己的阻止发布/订阅模式,如下所示。

use std::any::{Any, TypeId};

#[derive(Clone)]
struct ModelA {
    pub id: u32
}

#[derive(Clone)]
struct ModelB {
    pub id: u32
}

struct ModelASubscriberOne<'a> {
    pub model: &'a ModelA
}

impl<'a> Subscriber<u32> for ModelASubscriberOne<'a> {
    fn get_type(&self) -> TypeId {
        TypeId::of::<ModelASubscriberOne>()
    }

    fn execute(&self) {
        println!("SubscriberOne ModelA id: {}", self.model.id);
    }

    fn id(&self) -> u32 {
        self.model.id
    }
}

struct ModelASubscriberTwo<'a> {
    pub model: &'a ModelA
}

impl<'a> Subscriber<u32> for ModelASubscriberTwo<'a> {
    fn get_type(&self) -> TypeId {
        TypeId::of::<ModelASubscriberTwo>()
    }

    fn execute(&self) {
        println!("SubscriberTwo ModelA id: {}", self.model.id);
    }
    
    fn id(&self) -> u32 {
        self.model.id
    }
}

trait Subscriber<TKey:Eq + 'static> {
 fn get_type(&self) -> TypeId;
 fn execute(&self);
 fn id(&self) -> TKey;
 fn filter(&self, other: TKey) -> bool{
     self.id() == other
 }
}

struct Publisher<'a> {
    pub subscribers: Vec<&'a dyn Subscriber<u32>>
}

impl<'a> Publisher<'a> {
    fn new() -> Publisher<'a> {
        Publisher{subscribers: Vec::new()}
    }
    fn subscribe(&mut self, subscriber: &'a dyn Subscriber<u32>) {
        self.subscribers.push(subscriber);
    }

    fn publish<T>(&self) where T: 'static + Subscriber<u32> {
        self.subscribers.iter().filter(|x| {
            TypeId::of::<T>() == x.get_type()
        })
        .for_each(|x| {
            x.execute();
        });
    }

    fn unsubscribe<T:Any>(&mut self, subscriber: u32) {
        let position = self.subscribers.iter().position(|x| {
            TypeId::of::<T>() == x.get_type() && x.filter(subscriber)
        });
        match position {
            Some(position) => {
                self.subscribers.remove(position);
            },
            _ => {}
        }
    }
}

fn main() {
    let model_a = ModelA{id:0};
    let mut model_a_list: Vec<ModelA> = Vec::new();
    model_a_list.push(model_a);
    let model_a = ModelA{id:1};
    model_a_list.push(model_a);
    let mut publisher = Publisher::new();
    let subscriber = ModelASubscriberOne{model: &model_a_list[0]};
    publisher.subscribe(&subscriber);
    let subscriber = ModelASubscriberOne{model: &model_a_list[1]};
    publisher.subscribe(&subscriber);
    let subscriber = ModelASubscriberTwo{model: &model_a_list[1]};
    publisher.subscribe(&subscriber);
    println!("Subscribed");
    publisher.publish::<ModelASubscriberOne>();
    publisher.publish::<ModelASubscriberTwo>();
    publisher.unsubscribe::<ModelASubscriberOne>(model_a_list[1].id);
    println!("Unsubscribed");
    publisher.publish::<ModelASubscriberOne>();
    publisher.publish::<ModelASubscriberTwo>();
}

我认为能够为订户使用get_type()的默认实现(返回Self的TypeId)会有所帮助。有办法吗?

我尝试了以下操作:

trait Subscriber<TKey:Eq + 'static> {
    fn get_type(self: &Self) -> TypeId {
        TypeId::of::<Self>()
    }
// <...>
}

我收到以下消息:

error[E0310]: the parameter type `Self` may not live long enough
  --> src\main.rs:51:5
   |
51 |     TypeId::of::<Self>()
   |     ^^^^^^^^^^^^^^^^^^
   |
   = help: consider adding an explicit lifetime bound `Self: 'static`...
   = note: ...so that the type `Self` will meet its required lifetime bounds

我不确定将终身限制放在何处。我希望我也需要绑定Any特征,但是我不确定在哪放置。

谢谢。

0 个答案:

没有答案