下面的实现看起来很简单。由于某种原因我不明白问题是什么。编译器无法编译。
这里的主要问题是我无法更改函数 test(bool)
的声明因为它超出了框架。
/// Implemented in a 3rd party framework:
trait Share {
fn dosomething();
}
impl Share for String {
fn dosomething() {
todo!()
}
}
/// My part of the implementation:
// this function `test` will be handed over (as a function) to a framework method, which I can't change it's return type.
fn test(data: bool) -> Result<impl Share, String> {
return if data {
Ok(Data {})
} else {
Ok("a string".to_string())
}
}
struct Data {
}
impl Share for Data {
fn dosomething() {
todo!()
}
}
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/lib.rs:5:12
|
5 | Ok("a string".to_string())
| ^^^^^^^^^^^^^^^^^^^^^^ expected struct `Data`, found struct `String`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error
最佳答案
问题在于 if
的两个分支-else
表达式的计算结果必须为相同类型的值。但是,在您的代码中:
fn test(data: bool) -> Result<impl Share, String> {
return if data {
Ok(Data {}) // : Result<Data, String>
} else {
Ok("a string".to_string()) // : Result<String, String>
}
}
第一个分支的计算结果为Ok(Data {})
,因此其类型将被推断为 Result<Data, String>
,而第二个分支的计算结果为 Ok("a string".to_string())
它将被推断为 Result<String, String>
。由于这些类型不同,因此会导致编译时错误。
如果Share
是 object-safe trait ,例如:
trait Share {
fn dosomething(&self);
}
然后,由于值 Data{}
和"a string".to_string()
实现Share
,您可以通过将它们放入 Box<dyn Share>
将它们变成特征对象 。这样,您仍然可以通过依赖动态多态性来实现(运行时X)类型删除:
fn test(data: bool) -> Result<Box<dyn Share>, String> {
return if data {
Ok(Box::new(Data{}))
} else {
Ok(Box::new("a string".to_string()))
}
}
请注意,这里两个分支值的类型相同:Result<Box<dyn Share>, String>
因为类型 Box<Share>
和Box<String>
在运行时删除为 Box<dyn Share>
.
X您的目标是使用初始 impl Share
进行编译时类型删除。 .
关于rust - 使用不同的实现返回 Trait 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72705195/