[英]Combine traits with associated types in rust
I'm trying to create a kind of wrapper trait that combines multiples traits and a function that return the associated implementation of the trait.我正在尝试创建一种包装器特征,它结合了多个特征和一个 function 返回特征的相关实现。 It works well as long as you don't have associated types.
只要您没有关联类型,它就可以正常工作。 I don't know how to refer to the
Output
type I am aware of how to combine traits: Is there a way to combine multiple traits in order to define a new trait?我不知道如何引用
Output
类型我知道如何组合特征: 有没有办法组合多个特征以定义新特征? Is there any way to create a type alias for multiple traits? 有没有办法为多个特征创建类型别名?
But unfortunately, I've not found anything with associated types但不幸的是,我没有发现任何关联类型
Here is a summarized example of where I'm stucked这是我被困在哪里的总结示例
use std::ops::Add;
pub trait Hello {
fn hello(&self);
}
pub trait Goodbye {
fn goodbye(&self);
}
struct Suffix {
suffix: String,
}
pub struct World {
content: String,
}
impl World {
fn new(content: String) -> Self {
World { content: content }
}
}
impl Hello for World {
fn hello(&self) {
println!("Hello {}", self.content)
}
}
impl Goodbye for World {
fn goodbye(&self) {
println!("Goodbye {}", self.content)
}
}
impl Add<Suffix> for World {
type Output = World;
fn add(self, other: Suffix) -> World {
let suffixed: String = self.content + &other.suffix;
World::new(suffixed)
}
}
trait HelloGoodbye: Hello + Goodbye {}
impl<T> HelloGoodbye for T where T: Hello + Goodbye {}
fn get_hello_goodbye() -> Box<dyn HelloGoodbye> {
Box::new(World::new("Everyone".to_string()))
}
trait SuffixableHello: Hello + Add<Suffix, Output = Self> {}
impl<T> SuffixableHello for T where T: Hello + Add<Suffix, Output = Self> {}
fn get_suffixable_hello() -> Box<dyn SuffixableHello> {
Box::new(World::new("Everyone".to_string()))
}
fn main() {
// This works
let hello_goodbye = get_hello_goodbye();
hello_goodbye.hello();
hello_goodbye.goodbye();
// This does not work
let suffixable_hello = get_suffixable_hello();
suffixable_hello.hello()
}
I got this compilation error:我收到此编译错误:
49 | fn get_suffixable_hello() -> Box<dyn SuffixableHello> {
| ^^^^^^^^^^^^^^^ help: specify the associated type: `SuffixableHello<Output = Type>`
What am I supposed to put there?我应该把什么放在那里?
What I've try so far:到目前为止我尝试了什么:
trait SuffixableHello<T>: Hello + Add<Suffix, Output = T> {}
impl<T, U> SuffixableHello<T> for T where T: Hello + Add<Suffix, Output = Self> {}
And I get我得到
|
49 | fn get_suffixable_hello() -> Box<dyn SuffixableHello<T>> {
| ~~~~~~~~~~~~~~~~~~
Where am I supposed to add this T
generic?我应该在哪里添加这个
T
泛型? Does my fucntion need to be generic?我的功能需要通用吗?
trait SuffixableHello: Hello + Add<Suffix> {}
impl<T> SuffixableHello for T where T: Hello + Add<Suffix, Output = T> {}
But I get:但我得到:
the value of the associated type `Output` (from trait `Add`) must be specified
This makes sense since Output is not declared in the trait.这是有道理的,因为 Output 没有在特征中声明。
World
by Self
in the impl Add<Suffix> for World
impl Add<Suffix> for World
中用Self
替换World
Am I missing something here?我在这里错过了什么吗? Thank you
谢谢
Also, what if we want to return from the get_suffixable_hello()
one of two Hello
implementations, let's say World
and World2
to cite @cadolphs like in this doc https://doc.rust-lang.org/rust-by-example/trait/dyn.html此外,如果我们想从两个
Hello
实现之一的get_suffixable_hello()
返回怎么办,假设World
和World2
引用 @cadolphs 就像在这个文档https://doc.rust-lang.org/rust-by-example/特征/动态.html
fn get_suffixable_hello() -> Box<dyn SuffixableHello<Output=World>> {
Box::new(World::new("Everyone".to_string()))
}
does the trick.做的伎俩。
EDIT: Longer explanation.编辑:更长的解释。 Your first initial compiler error tells you that you can't just return
Box<dyn SuffixableHello>
.您的第一个初始编译器错误告诉您不能只返回
Box<dyn SuffixableHello>
。 That's because having the same trait but with different associated types isn't allowed, because the signatures of associated methods would be different.这是因为不允许具有相同的特征但具有不同的关联类型,因为关联方法的签名会不同。
So.所以。 We need to put a type there.
我们需要在那里放一个类型。 And what should that type be?
那种类型应该是什么? Well, given that you're explicitly calling
World::new
, there's really only one type that makes sense here, and that's World
.好吧,鉴于您显式调用
World::new
,这里实际上只有一种类型有意义,那就是World
。
In your toy example that makes it of course a bit silly and redundant because there's only one struct that implements all those traits.在您的玩具示例中,这当然有点愚蠢和多余,因为只有一个结构可以实现所有这些特征。
If you had another struct, World2
, you could not have it be returned by get_suffixable_hello
next to World
, because World2
would have associated type Output=World2
and hence wouldn't match the Output=World
associated type.如果您有另一个结构
World2
,则无法通过World
旁边的get_suffixable_hello
返回它,因为World2
将具有关联类型Output=World2
,因此不会匹配Output=World
关联类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.