如何让调用者看到方法的特征实现?
How do I make a caller see the trait implementation of a method?
使用代码:
trait Msg {
fn apply_to_state(&self, state: &mut State);
}
trait ApplicableToStateOne: Msg {
fn apply_to_state(&self, state: &mut State) {
match state {
State::StateOne(s) => {
self.apply_to_state_one(s)
}
_ => {
//TODO: return an error
}
}
}
fn apply_to_state_one(&self, state_one: &mut StateOne);
}
#[derive(Debug, Clone)]
pub struct MsgA {
pub field_a: u8,
}
impl Msg for MsgA {}
impl ApplicableToStateOne for MsgA {
fn apply_to_state_one(&self, state_one: &mut StateOne) {
state_one.one_special += 31; // just a mutability test
}
}
// this is a stub for receiving different kinds of messages from the network
fn recv() -> Box<dyn Msg> {
Box::new(MsgA { field_a: 42 })
}
fn main() {
let mut state = State::StateOne(StateOne { common: 0, one_special: 1 });
for _ in 0..100 { // this would be loop, but that makes the playground timeout
let incoming = recv(); // this would block
incoming.apply_to_state(&mut state)
}
}
编译器抱怨:
error[E0046]: not all trait items implemented, missing: `apply_to_state`
--> src/bin/sandbox6.rs:83:1
|
2 | fn apply_to_state(&self, state: &mut State);
| -------------------------------------------- `apply_to_state` from trait
...
83 | impl Msg for MsgA {}
| ^^^^^^^^^^^^^^^^^ missing `apply_to_state` in implementation
在我(显然有缺陷)的理解中,我本以为会调用 apply_to_state
的 trait ApplicableToStateOne
实现。
我怎样才能做到这一点?
更新:
更抽象地说,这个问题是关于:
- 从网络接收一个装箱的超特征对象,然后
- 找出它有哪个子特征,最后
- 调用适合子特征的方法(可能以某种方式通过超特征)。
这一切都可以完成,相当冗长,使用枚举而不是特征,但这增加了枚举的层次结构。
枚举层次结构不好,因为:
- 它向序列化添加了不必要的字节,因为
- 只能有一个这样的层次结构,这会阻止以任何其他方式对邮件进行分类。
考虑要链接到 Trait
而不是对象本身的每个方法。
检查这个更简单的例子:
trait Foo {
fn foo(&self) -> &'static str;
}
trait FooPrime {
fn foo(&self) -> &'static str;
}
struct Bar {}
impl Foo for Bar {
fn foo(&self) -> &'static str {
"foo"
}
}
impl FooPrime for Bar {
fn foo(&self) -> &'static str {
"foo prime"
}
}
fn main() {
let bar = Bar{};
println!("{} : {}", bar.foo(), bar.foo());
}
编译时出现以下错误:
Compiling playground v0.0.1 (/playground)
error[E0034]: multiple applicable items in scope
--> src/main.rs:25:29
|
25 | println!("{} : {}", bar.foo(), bar.foo());
| ^^^ multiple `foo` found
|
note: candidate #1 is defined in an impl of the trait `Foo` for the type `Bar`
--> src/main.rs:12:5
|
12 | fn foo(&self) -> &'static str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in an impl of the trait `FooPrime` for the type `Bar`
--> src/main.rs:18:3
|
18 | fn foo(&self) -> &'static str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #1
|
25 | println!("{} : {}", Foo::foo(&bar), bar.foo());
| ^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #2
|
25 | println!("{} : {}", FooPrime::foo(&bar), bar.foo());
| ^^^^^^^^^^^^^^^^^^^
error[E0034]: multiple applicable items in scope
--> src/main.rs:25:40
|
25 | println!("{} : {}", bar.foo(), bar.foo());
| ^^^ multiple `foo` found
|
note: candidate #1 is defined in an impl of the trait `Foo` for the type `Bar`
--> src/main.rs:12:5
|
12 | fn foo(&self) -> &'static str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in an impl of the trait `FooPrime` for the type `Bar`
--> src/main.rs:18:3
|
18 | fn foo(&self) -> &'static str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #1
|
25 | println!("{} : {}", bar.foo(), Foo::foo(&bar));
| ^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #2
|
25 | println!("{} : {}", bar.foo(), FooPrime::foo(&bar));
我们需要明确告诉编译器使用哪个方法:
fn main() {
let bar = Bar{};
println!("{} : {}", Foo::foo(&bar), FooPrime::foo(&bar));
}
出于同样的原因,在您的代码中未使用其他特征的方法,因为它不是先前特征的一部分。
这是一个link to the book
您可能希望使用 supertrait 功能来创建基于“父”特征的另一个特征的默认实现:
trait FooPrime : Foo {
fn foo(&self) -> &'static str {
Foo::foo(self)
}
}
您可以使用泛型来为所有实现 ApplicableToStateOne
:
的东西实现 Msg
struct State {}
trait Msg {
fn apply_to_state(&self, state: &mut State);
}
trait ApplicableToStateOne: Msg {
fn apply_to_state_one(&self, state: &mut State) {
todo!();
}
}
impl<T: ApplicableToStateOne> Msg for T {
fn apply_to_state(&self, state: &mut State) {
self.apply_to_state_one (state);
}
}
#[derive(Debug, Clone)]
pub struct MsgA {
pub field_a: u8,
}
impl ApplicableToStateOne for MsgA {}
// No need to implement Msg explicitly for MsgA
使用代码:
trait Msg {
fn apply_to_state(&self, state: &mut State);
}
trait ApplicableToStateOne: Msg {
fn apply_to_state(&self, state: &mut State) {
match state {
State::StateOne(s) => {
self.apply_to_state_one(s)
}
_ => {
//TODO: return an error
}
}
}
fn apply_to_state_one(&self, state_one: &mut StateOne);
}
#[derive(Debug, Clone)]
pub struct MsgA {
pub field_a: u8,
}
impl Msg for MsgA {}
impl ApplicableToStateOne for MsgA {
fn apply_to_state_one(&self, state_one: &mut StateOne) {
state_one.one_special += 31; // just a mutability test
}
}
// this is a stub for receiving different kinds of messages from the network
fn recv() -> Box<dyn Msg> {
Box::new(MsgA { field_a: 42 })
}
fn main() {
let mut state = State::StateOne(StateOne { common: 0, one_special: 1 });
for _ in 0..100 { // this would be loop, but that makes the playground timeout
let incoming = recv(); // this would block
incoming.apply_to_state(&mut state)
}
}
编译器抱怨:
error[E0046]: not all trait items implemented, missing: `apply_to_state`
--> src/bin/sandbox6.rs:83:1
|
2 | fn apply_to_state(&self, state: &mut State);
| -------------------------------------------- `apply_to_state` from trait
...
83 | impl Msg for MsgA {}
| ^^^^^^^^^^^^^^^^^ missing `apply_to_state` in implementation
在我(显然有缺陷)的理解中,我本以为会调用 apply_to_state
的 trait ApplicableToStateOne
实现。
我怎样才能做到这一点?
更新:
更抽象地说,这个问题是关于:
- 从网络接收一个装箱的超特征对象,然后
- 找出它有哪个子特征,最后
- 调用适合子特征的方法(可能以某种方式通过超特征)。
这一切都可以完成,相当冗长,使用枚举而不是特征,但这增加了枚举的层次结构。
枚举层次结构不好,因为:
- 它向序列化添加了不必要的字节,因为
- 只能有一个这样的层次结构,这会阻止以任何其他方式对邮件进行分类。
考虑要链接到 Trait
而不是对象本身的每个方法。
检查这个更简单的例子:
trait Foo {
fn foo(&self) -> &'static str;
}
trait FooPrime {
fn foo(&self) -> &'static str;
}
struct Bar {}
impl Foo for Bar {
fn foo(&self) -> &'static str {
"foo"
}
}
impl FooPrime for Bar {
fn foo(&self) -> &'static str {
"foo prime"
}
}
fn main() {
let bar = Bar{};
println!("{} : {}", bar.foo(), bar.foo());
}
编译时出现以下错误:
Compiling playground v0.0.1 (/playground)
error[E0034]: multiple applicable items in scope
--> src/main.rs:25:29
|
25 | println!("{} : {}", bar.foo(), bar.foo());
| ^^^ multiple `foo` found
|
note: candidate #1 is defined in an impl of the trait `Foo` for the type `Bar`
--> src/main.rs:12:5
|
12 | fn foo(&self) -> &'static str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in an impl of the trait `FooPrime` for the type `Bar`
--> src/main.rs:18:3
|
18 | fn foo(&self) -> &'static str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #1
|
25 | println!("{} : {}", Foo::foo(&bar), bar.foo());
| ^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #2
|
25 | println!("{} : {}", FooPrime::foo(&bar), bar.foo());
| ^^^^^^^^^^^^^^^^^^^
error[E0034]: multiple applicable items in scope
--> src/main.rs:25:40
|
25 | println!("{} : {}", bar.foo(), bar.foo());
| ^^^ multiple `foo` found
|
note: candidate #1 is defined in an impl of the trait `Foo` for the type `Bar`
--> src/main.rs:12:5
|
12 | fn foo(&self) -> &'static str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in an impl of the trait `FooPrime` for the type `Bar`
--> src/main.rs:18:3
|
18 | fn foo(&self) -> &'static str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #1
|
25 | println!("{} : {}", bar.foo(), Foo::foo(&bar));
| ^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #2
|
25 | println!("{} : {}", bar.foo(), FooPrime::foo(&bar));
我们需要明确告诉编译器使用哪个方法:
fn main() {
let bar = Bar{};
println!("{} : {}", Foo::foo(&bar), FooPrime::foo(&bar));
}
出于同样的原因,在您的代码中未使用其他特征的方法,因为它不是先前特征的一部分。 这是一个link to the book
您可能希望使用 supertrait 功能来创建基于“父”特征的另一个特征的默认实现:
trait FooPrime : Foo {
fn foo(&self) -> &'static str {
Foo::foo(self)
}
}
您可以使用泛型来为所有实现 ApplicableToStateOne
:
Msg
struct State {}
trait Msg {
fn apply_to_state(&self, state: &mut State);
}
trait ApplicableToStateOne: Msg {
fn apply_to_state_one(&self, state: &mut State) {
todo!();
}
}
impl<T: ApplicableToStateOne> Msg for T {
fn apply_to_state(&self, state: &mut State) {
self.apply_to_state_one (state);
}
}
#[derive(Debug, Clone)]
pub struct MsgA {
pub field_a: u8,
}
impl ApplicableToStateOne for MsgA {}
// No need to implement Msg explicitly for MsgA