【发布时间】:2017-03-06 07:38:54
【问题描述】:
我有这个代码 (playground):
use std::sync::Arc;
pub trait Messenger : Sync + Send {
fn send_embed<F: FnOnce(String) -> String>(&self, u64, &str, f: F)
-> Option<u64> where Self: Sync + Send;
}
struct MyMessenger {
prefix: String,
}
impl MyMessenger {
fn new(s: &str) -> MyMessenger {
MyMessenger { prefix: s.to_owned(), }
}
}
impl Messenger for MyMessenger {
fn send_embed<F: FnOnce(String) -> String>(&self, channel_id: u64, text: &str, f: F) -> Option<u64> {
println!("Trying to send embed: chid={}, text=\"{}\"", channel_id, text);
None
}
}
struct Bot {
messenger: Arc<Messenger>,
}
impl Bot {
fn new() -> Bot {
Bot {
messenger: Arc::new(MyMessenger::new("HELLO")),
}
}
}
fn main() {
let b = Bot::new();
}
我想做一个多态对象(特征Messenger,多态实现之一是MyMessenger)。但是当我尝试编译它时出现错误:
error[E0038]: the trait `Messenger` cannot be made into an object
--> <anon>:25:5
|
25 | messenger: Arc<Messenger>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Messenger` cannot be made into an object
|
= note: method `send_embed` has generic type parameters
我发现在这种情况下我必须要求Sized,但这并不能解决它。如果我将 send_embed 方法更改为以下内容:
fn send_embed<F: FnOnce(String) -> String>(&self, u64, &str, f: F)
-> Option<u64> where Self: Sized + Sync + Send;
然后编译成功但是:
- 这里为什么需要
Sized?如果我们不能从 trait 对象中使用此方法,这将违反多态性。 -
我们实际上不能从
Arc<Messenger>使用这个方法然后:fn main() { let b = Bot::new(); b.messenger.send_embed(0u64, "ABRACADABRA", |s| s); }给予:
error[E0277]: the trait bound `Messenger + 'static: std::marker::Sized` is not satisfied --> <anon>:37:17 | 37 | b.messenger.send_embed(0u64, "ABRACADABRA", |s| s); | ^^^^^^^^^^ the trait `std::marker::Sized` is not implemented for `Messenger + 'static` | = note: `Messenger + 'static` does not have a constant size known at compile-time
我完全被困在这里。不知道如何在 trait 中使用带有泛型方法的多态性。有什么办法吗?
【问题讨论】:
-
这与trait object 和“对象安全”的概念有关,已经讨论了很多......但我找不到一个很好的副本来详细解释这个问题。
-
this question 的答案可能会有所帮助。
-
@AleksanderFular 您是否尝试在操场上更正代码?因为在你说之前我已经尝试过了,不幸的是这对我没有帮助。在您发表评论后,我再次尝试了,without any success.