当前位置: 首页 > 知识库问答 >
问题:

创建特征对象的向量

百里弘致
2023-03-14

我正在尝试创建一个特征对象的向量,但我得到了类型不匹配。我还尝试使用. map()代替for循环,但遇到了同样的问题。这是我真实代码的最小版本,我意识到这个例子不需要使用特征对象,但我的真实代码需要,因为列表中除了Link之外还有其他类型,它们也实现了Speak。如何使用正确的类型创建Vec以便将其传递给trait_objects

use std::fs;

fn main() {
    // let links = fs::read_dir("my_dir").unwrap();
    // let links: Vec<Box<dyn Speak>> = links
    //     .map(|file| {
    //         let myfile = file.unwrap();
    //         let href = myfile.path().to_str().unwrap();
    //         Box::new(Link { attr: href })
    //     })
    //     .collect();

    let links = Vec::new();
    for entry in fs::read_dir("my_dir").unwrap() {
        let myfile = entry.unwrap();
        let href = myfile.path().to_str().unwrap();
        links.push(Box::new(Link { attr: href }));
    }

    let link_objects = ListOfTraitObjects {
        trait_objects: links,
    };
    for link in link_objects.trait_objects.iter() {
        println!("{}", link.speak());
    }
}
trait Speak {
    fn speak(&self) -> String;
}

struct ListOfTraitObjects {
    trait_objects: Vec<Box<dyn Speak>>,
}

struct Link<'a> {
    attr: &'a str,
}
impl Speak for Link<'_> {
    fn speak(&self) -> String {
        self.attr.to_string()
    }
}

共有1个答案

邹斌
2023-03-14

您的代码存在几个问题。首先,您正在创建一个 Vec

links.push(Box::new(Link { attr: href }) as Box::<dyn Speak>);

游乐场

然而,这会产生两个新的错误:

error[E0716]: temporary value dropped while borrowed
 --> src/lib.rs:7:20
  |
7 |         let href = myfile.path().to_str().unwrap();
  |                    ^^^^^^^^^^^^^                  - temporary value is freed at the end of this statement
  |                    |
  |                    creates a temporary which is freed while still in use
8 |         links.push(Box::new(Link { attr: href }) as Box::<dyn Speak>);
  |                    ----------------------------- cast requires that borrow lasts for `'static`

error[E0596]: cannot borrow `links` as mutable, as it is not declared as mutable
 --> src/lib.rs:8:9
  |
4 |     let links = Vec::new();
  |         ----- help: consider changing this to be mutable: `mut links`
...
8 |         links.push(Box::new(Link { attr: href }) as Box::<dyn Speak>);
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable

第一个错误是因为 Link 结构从条目中借用了一个字符串,但条目只在当前循环迭代时存在。即使错误指出强制转换需要“静态生存期”,如果您只是尝试构建Vec,也会收到类似的错误

struct Link {
    attr: String,
}
impl Speak for Link {
    fn speak(&self) -> String {
        self.attr.clone()
    }
}

第二个错误更容易,只需按照编译器的建议将 let links = ... 替换为 let mut links = ...即可修复。

完整工作示例:

use std::fs;

fn main() {
    let mut links = Vec::new();
    for entry in fs::read_dir("my_dir").unwrap() {
        let myfile = entry.unwrap();
        let href = myfile.path().to_str().unwrap().to_string();
        links.push(Box::new(Link { attr: href }) as Box::<dyn Speak>);
    }

    let link_objects = ListOfTraitObjects {
        trait_objects: links,
    };
    for link in link_objects.trait_objects.iter() {
        println!("{}", link.speak());
    }
}
trait Speak {
    fn speak(&self) -> String;
}

struct ListOfTraitObjects {
    trait_objects: Vec<Box<dyn Speak>>,
}

struct Link {
    attr: String,
}
impl Speak for Link {
    fn speak(&self) -> String {
        self.attr.clone()
    }
}

游乐场

同样的修复也可以应用于基于迭代器的解决方案:

let links = fs::read_dir("my_dir").unwrap();
let links: Vec<_> = links
    .map(|file| {
        let myfile = file.unwrap();
        let href = myfile.path().to_str().unwrap().to_string();
        Box::new(Link { attr: href }) as Box<dyn Speak>
    })
    .collect();

游乐场

 类似资料:
  • (这是我第二次尝试追踪我的确切问题。查看编辑历史记录) 我有一个简单的通用特性和两种不同的实现: 我现在想要一个包含两个实现元素的向量。正如我在这里学到的,我做: 但是编译器不同意: 一方面,这是有道理的。另一方面,我应该为写什么?我希望它是通用的,所以我不能简单地在那里放或。我可以做

  • 考虑以下代码: 当我尝试推送<code>cat</code>时,编译器告诉我<code>v</code>是<code>动物</code>的向量(类型不匹配) 那么,如何制作一个属于trait的对象向量,并在每个元素上调用相应的trait方法呢?

  • 本文向大家介绍Java面向对象的三大特征,包括了Java面向对象的三大特征的使用技巧和注意事项,需要的朋友参考一下   java面向对象的三大特征:“封装、继承、多态”。更多Java技术知识,请登陆疯狂软件教育官网。微信搜索微信号:疯狂软件,参加2015年优惠活动,有机会获得优惠劵和代金劵。   以本文为例,User类中的变量为私有变量,只能通过创建对象(此时构造方法自动调用)来赋值。   外界只

  • 关于一个语言被称为面向对象所需的功能,在编程社区内并未达成一致意见。Rust 被很多不同的编程范式影响,包括面向对象编程;比如第十三章提到了来自函数式编程的特性。面向对象编程语言所共享的一些特性往往是对象、封装和继承。让我们看一下这每一个概念的含义以及 Rust 是否支持他们。In my view the Gang of Four is the best book ever written on

  • trait对象在Rust中是指使用指针封装了的 trait,比如 &SomeTrait 和 Box<SomeTrait>。 trait Foo { fn method(&self) -> String; } impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } } impl Foo for String