创建在 Rust 中实现特征的对象向量

2023-12-07

用Java来说,我试图创建一个对象(严格实例)的集合(向量),每个对象都实现一个接口(特征),因此我可以迭代该集合并对所有对象调用一个方法。

我已将其缩减为下面的一个示例文件,其中包含我希望能够更轻松地获得答案的所有部分。

// main.rs - try and compile using just "rustc main.rs"
use std::io::Result;

/// ////// Part 1
// Types used by implementors of the trait, and in creating a vector of implementors of the trai
pub struct SampleResult {
    metric: String,
}

pub trait SampleRunner {
    fn run(&self, &'static str) -> Result<SampleResult>;
}

pub struct Sample {
    name: &'static str,
    runner: &'static SampleRunner,
}

/// /////// Part 2
/// Create one specific static instance of such as Sample
static SAMPLE1: Sample = Sample {
    name: "sample",
    runner: &Sample1,
};

// need a struct to hold the run method to satisfy the trait???
struct Sample1;

// Implement the trait for this specific struct
impl SampleRunner for Sample1 {
    fn run(&self, name: &'static str) -> Result<SampleResult> {
        println!("Name: {}", name);
        Ok(SampleResult { metric: "OK".to_string() })
    }
}

/// /////// Part 3
/// Using the existing static instances of Sample struct, by creating a vector of references for them
/// then iterating over the vector and calling the trait method on each one
fn main() {
    let sample_set: Vec<&Sample> = vec![&SAMPLE1];

    for sample in sample_set.iter() {
        match sample.runner.run(sample.name) {
            Ok(result) => println!("Success"),
            _ => panic!("failed"),
        }
    }
}

该特定示例失败并显示以下消息:

error[E0277]: the trait bound `SampleRunner + 'static: std::marker::Sync` is not satisfied in `Sample`
  --> <anon>:21:1
   |
21 |   static SAMPLE1: Sample = Sample {
   |  _^ starting here...
22 | |     name: "sample",
23 | |     runner: &Sample1,
24 | | };
   | |__^ ...ending here: within `Sample`, the trait `std::marker::Sync` is not implemented for `SampleRunner + 'static`
   |
   = note: `SampleRunner + 'static` cannot be shared between threads safely
   = note: required because it appears within the type `&'static SampleRunner + 'static`
   = note: required because it appears within the type `Sample`
   = note: shared static variables must have a type that implements `Sync`

但根据我采取的方法,我遇到了许多不同的问题,与Sync, Sized等等等等


代码中有两个小错误。第一个是错误所描述的,它告诉我们静态值不安全,因为它没有实现 Sync 特征。它只是尝试为从多个线程操作静态值的情况做好准备。在这里,最好的解决方案是将值标记为const。之后,寿命就会出现一些问题&SAMPLE1在 main 中,可以通过“使用 let 关键字来增加其生命周期”来解决。

经过这些小修改后的代码可以编译,如下所示:

use std::io::{Result};

pub struct SampleResult {
    metric: String
}

pub trait SampleRunner {
    fn run(&self, &'static str) -> Result<SampleResult>;
}

pub struct Sample {
    name: &'static str,
    runner: &'static SampleRunner
}

// Make it const
const SAMPLE1: Sample = Sample { name: "sample", runner: &Sample1 };

struct Sample1;

impl SampleRunner for Sample1 {
    fn run(&self, name: &'static str) -> Result<SampleResult> {
        println!("Name: {}", name);
        Ok(SampleResult {metric: "OK".to_string() })
    }
}

fn main() {
    // Extend the lifetime of the borrow by assigning it to a scope variable
    let borrowed_sample1 : &Sample = &SAMPLE1;
    let sample_set: Vec<&Sample> = vec!(borrowed_sample1);

    for sample in sample_set.iter() {
        match sample.runner.run(sample.name) {
        Ok(result) => println!("Success"),
        _ => panic!("failed")
        }
    }
}

但是,我发现您对代码不满意,因为您必须为每个实现创建一个新的结构SampleRunner。还有另一种方法,使用 lambda 函数(Rust 文档只是将它们称为Closures).

use std::io::{Result};

pub struct SampleResult {
    metric: String
}

type SampleRunner = Fn(&'static str) -> Result<SampleResult>;

pub struct Sample {
    name: &'static str,
    runner: &'static SampleRunner
}

// Still const, use a lambda as runner    
const SAMPLE1: Sample = Sample { name: "sample", runner: &|name| {
  println!("Name: {}", name);
  Ok(SampleResult {metric: "OK".to_string() })
} };

fn main() {
    let borrowed_sample1 : &Sample = &SAMPLE1;
    let sample_set: Vec<&Sample> = vec!(borrowed_sample1);

    for sample in sample_set.iter() {
        // Must parenthese sample.runner so rust knows its a field not a method
        match (sample.runner)(sample.name) {
        Ok(result) => println!("Success"),
        _ => panic!("failed")
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建在 Rust 中实现特征的对象向量 的相关文章

随机推荐

  • Prestashop 1.7 客户密码加密?

    我为 Prestashop 1 6 制作了一些基于 php 的第三方系统 它可以直接连接 Prestashop 数据库 我已将 Presta 升级到 1 7 5 1 并且可以正常使用 只是它不再登录客户 因为正如我所看到的 密码加密已更改
  • xcode 中 .strings 文件中的杂注标记替代是什么?

    pragma mark 适用于 h 文件 在 strings 文件中使用什么来实现相同的效果 A strings文件基本上是一个具有特殊格式的plist文件 也就是说 它不是编译器的输入文件 这也意味着 一个 pragma不允许出现在 pl
  • 如何从 Spring Data MongoDB 中的 MongoDB ObjectId 中提取时间戳?

    MongoDB文档建议从 ObjectId 中提取插入时间 而不是使用单独的时间字段 有谁知道如何使用 Spring Data MongoDB 做到这一点 特别是 我想查询在特定日期范围内插入的文档 很容易从ObjectId 但是你没有得到
  • 当父文档可能不存在时更新 MongoDB 子文档

    这是我的数据 包括books集合 具有书评子集合 books id ObjectId 5558f40ad498c653748cf045 title Widget XYZ isbn 1234567890 reviews id ObjectId
  • R将具有开始和结束年份的数据帧转换为时间序列[重复]

    这个问题在这里已经有答案了 我想将具有起始年和结束年变量的数据框转换为完整的时间序列 其中 1 包含起始年和结束年之间的所有年份 2 填写以下值其间年份的所有变量 原始数据如下所示 data original lt data frame n
  • Hyperledger Fabric:对等链码实例化错误

    启动容器时出错 无法生成特定于平台的 docker 构建 从构建返回错误 1 无法加载包 包 bin github com hyperledger fabric chaincode marbles 打开 bin github com hyp
  • 我应该如何使用 createJs 创建响应式画布以适应不同移动设备的屏幕?

    我想开发一款html5手机游戏 如您所知 移动设备的屏幕尺寸不同 因此我想创建一个响应式画布 以便它可以适应不同的屏幕 最简单的方法是根据视口使用 JavaScript 调整画布大小 然后重排内容 var w container width
  • Python 套接字从 Java PrintWriter 套接字接收不完整的消息

    我制作了一个 python 队列 类似于 JMS 协议 它将接收来自两个 Java 客户端的问题 python 服务器将从其中一个 Java 客户端接收消息 第二个客户端将读取问题并发布答案 连接和消息传递工作正常 当 Java 客户端用很
  • 是否可以在 C# 中使用带有 CA 证书的 .p12 文件而不将其导入证书存储区

    我得到了一个 p12 证书文件 其中包含 3 个证书 其中2个是CA证书 如果我使用curl Win10上的7 70 我可以这样做 curl s S i cert Swish Merchant TestCertificate 1234679
  • 我使用 long double 的方式有问题吗?

    我最近对学习 C 编程感兴趣 因为我想更深入地了解计算机的工作和处理指令的方式 我想我会尝试一下数据类型 但我真的不明白我的输出发生了什么 include
  • 用户控件或面板的自定义边框宽度和边框颜色

    我想在这里做同样的事情 Balazs Tihanyi https stackoverflow com a 9772020 8458887但使用 TableLayoutPanel 我测试了他的代码并且有效 但是当我更改 TableLayout
  • 鉴于存储私钥的新 FIPS 要求,是否有任何方法可以将代码签名证书放入 Azure Key Vault?

    我们订购了新的代码签名证书 并在基于 USB 的 硬件令牌 上获取了私钥 这与新的代码签名证书规则兼容 但这限制了对一台物理 PC 的访问 我们确实希望证书位于 Azure Key Vault 中 可从我们的构建代理 使用 azuresig
  • Tkinter focus_set 和 focus_force 未按预期工作

    我正在尝试拥有Entry打开新页面时获得焦点的字段 import tkinter as tk from tkinter import from tkinter import ttk class DIS tk Tk def init self
  • 如何临时模拟用户打开文件?

    我想暂时模拟域用户帐户以从 ASP NET 站点读取网络驱动器上的文件 我不想为整个站点设置模拟或在服务器上设置映射驱动器 我最终使用了代码Michiel van Otegem WindowsImpersonationContext 变得简
  • 状态栏问题

    正如您从我的图像中看到的 状态栏显示在我的表格视图的顶部 我不明白我做错了什么导致这种情况发生 我确信这将是一个简单的修复 但我只是想念它 任何帮助将不胜感激 谢谢 您可以通过在 ViewDidLoad 方法中编写以下代码来避免此问题 fl
  • 序列化/反序列化不同的属性名称?

    我有一个旧系统 在请求信息调用中返回 xml 其名称如下所示 邮政编码字段 名字字段 然后 同一系统有一个修改调用 它采用如下所示的 xml 邮政编码 名字 姓氏 有没有办法构建一个对象来反序列化请求 同时使用不同的名称序列化 xml 输出
  • 将 Linq-to-Sql 查询的 WHERE 子句作为参数传递

    这可能有点突破了 Linq to Sql 的界限 但考虑到到目前为止它的多功能性 我想我应该问一下 我有 3 个查询 它们选择相同的信息 仅在where子句 现在我知道我可以传递一个委托 但这只允许我过滤已经返回的结果 但我想通过参数构建查
  • $lookup 中其他连接条件的性能严重下降(使用管道)

    因此 在一些代码审查期间 我决定通过改进一个聚合来提高现有查询性能 如下所示 aggregate difference starts here lookup from sessions localField id foreignField
  • Android 10 中的 Android 开发者无 IMEI

    由于 Android 非常重视安全性 并试图让新的 Android 版本更加安全 因此开发人员很难跟上新的安全功能并找到旧方法的替代方案来使他们的应用程序与旧功能兼容 这个问题是关于新Android 10中的IMEI 旧方法通过使用以下代码
  • 创建在 Rust 中实现特征的对象向量

    用Java来说 我试图创建一个对象 严格实例 的集合 向量 每个对象都实现一个接口 特征 因此我可以迭代该集合并对所有对象调用一个方法 我已将其缩减为下面的一个示例文件 其中包含我希望能够更轻松地获得答案的所有部分 main rs try