rust - 无法将实现特征的结构装箱为特征对象

标签 rust traits box

我正在使用 Rust,代码如下:

pub trait TFilter {
    fn get_text(&self) -> &String;
}
...
pub struct ContentFilter {
    text: String,
    domains: String,
    body: String,
}

impl TFilter for ContentFilter {
    fn get_text(&self) -> &String {
        return &self.text
    }
}

impl ContentFilter {
    pub fn from_text(text: String, domains: String, body: String) -> Self {
        return ContentFilter {
            text,
            domains,
            body
        }
    }
}
...

fn filter_from_text(&mut self, text: String) -> &Box<dyn TFilter> {
...
&Box::new(ContentFilter::from_text(text, domains, body)) // is returned
...
}

我收到错误消息:

expected trait object dyn filter::TFilter, found struct filter::ContentFilter

= note: expected reference &std::boxed::Box<(dyn filter::TFilter + 'static)> found reference &std::boxed::Box<filter::ContentFilter>

这是误导性的:

  1. 它确实实现了该特征
  2. 编译器确实知道 ContentFilter 的大小结构

有什么线索吗?

PS。无论如何,代码都不好(因为不清楚谁拥有返回的 Box),但该消息具有误导性。

PPS。那么如何实现缓存代理:

pub trait TFilterBuilder {
    fn filter_from_text(&mut self, text: String) -> &Box<dyn TFilter>;
}
...
struct FilterCachingProxy {
    filter_builder: Box<dyn TFilterBuilder>,
    cache: Box<dyn TFilterCache>
}

impl FilterCachingProxy {
    fn new_for_builder(filter_builder: Box<dyn TFilterBuilder>, cache: Box<dyn TFilterCache>) -> Self {
        return FilterCachingProxy {
            filter_builder,
            cache
        }
    }
}

impl TFilterBuilder for FilterCachingProxy {
    fn filter_from_text(&mut self, text: String) -> &Box<dyn TFilter> {
        let boxed_filter = match self.cache.get(&text) {
            Some(found_boxed_filter) => found_boxed_filter,
            _ => {
                // delegate creation to wrapped TFilterBuilder impl (`filter_builder`)
                let boxed_filter = self.filter_builder.filter_from_text(text.clone());
                // ... and put to the cache
                self.cache.put(&text, &boxed_filter); // boxed_filter should be moved to make cache own it?
                &boxed_filter // looks strange: who owns it then?
            }
        };
        return boxed_filter;
    }
}

最佳答案

返回类型应该只是 Box ,不是对 Box 的引用:

fn filter_from_text(&mut self, text: String) -> Box<dyn TFilter> {
    ...
    Box::new(ContentFilter::from_text(text, domains, body)) // is returned
}

( Minimal compiling version on the playground )

该框是在您的函数中新创建的,因此您必须归还该框的所有权。不可能只返回对临时对象的引用,因为它将在函数末尾超出范围。

此更改的副作用是来自 Box<ContentFilter> 的未调整大小的强制转换至Box<dyn TFilter>现在将真正起作用。强制转换仅适用于强制转换站点,就像返回值一样。在您的代码中,需要强制转换的类型嵌套在引用中,因此编译器不会执行未指定大小的强制转换。

关于rust - 无法将实现特征的结构装箱为特征对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65916882/

相关文章:

multithreading - 为什么在返回 `Future::poll` 后没有重复调用 `NotReady` ?

rust - 堆栈溢出堆缓冲区?

css 框模型仅适用于内联样式定义...为什么?

javascript - 如何在 R 中的同一箱形图上绘制来自一个数据集的 2 组分类数据

go - BOX/JWT OAuth 2.0 由 golang

rust - 专注于在 Rust 中重用

linux - 我如何递归地观察 Rust 中的文件更改?

php - 使用 CakePHP 2 的特征和命名空间的正确方法是什么?

php - 如何在 PHP 中通过引用传递变量来存储变量?

Scala:在模式匹配中混合特征和案例类