rust - 使用不同的实现返回 Trait 实现

标签 rust traits

下面的实现看起来很简单。由于某种原因我不明白问题是什么。编译器无法编译。

这里的主要问题是我无法更改函数 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> 。由于这些类型不同,因此会导致编译时错误。


如果Shareobject-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/

相关文章:

rust - 使用 chrono 处理 rust 中的 unix 时间戳

rust - 如何编写不拥有(或不消耗)迭代器所有权的函数? [复制]

logging - 如何使用 log4rs 更改正在运行的进程的日志级别?

rust - GMP - mpf_cmp_si 对于负值无法正常工作

scala - 在 Scala 中定义要由 case 类扩展的特征

rust - 是否可以为由所有实现特征的类型组成的任何元组自动实现特征?

php - 使用 trait 为接口(interface)定义函数的目的是什么

模板化类型的 C++ 模板特化

rust - 如何访问当前平台的文件路径分隔符?

rust - 为什么 impl trait 不能用于返回多个/条件类型?