首页 > 解决方案 > 构造类型的向量并初始化它们

问题描述

我试图拥有某种类型的列表,然后我可以初始化和构建遗传算法。

问题在于使用“类型”本身,我还没有找到正确的方法来获取一系列类型并调用::new每个类型来获取“实例”。

// --- conditions.rs ----------------------------------
extern crate strum;
use strum_macros::{EnumIter}; // etc.

pub trait Testable {
    fn new() -> Self;
    fn test(&self, candle: &Candle) -> bool;
}

// use strum::IntoEnumIterator;
#[derive(EnumIter,Debug)]
pub enum Conditions {
    SmaCheck,
    CandlesPassed,
}

// simple moving average check
pub struct SmaCheck {
    sma1: i8,
    sma2: i8,
}

impl Testable for SmaCheck {
    fn new() -> Self {
        Self { sma1: 10, sma2: 20 }
    }
    fn test(&self, candle: &Candle) -> bool {
        return true;
    }
}


// --- generator.rs -----------------------------------
// creates random conditions, which will then be mutated and bred

use strum::IntoEnumIterator;
use crate::conditions::{Conditions, Testable};


pub fn run() {
    for condition in Conditions::iter() {
        println!("{:?}", condition); // this works

        let testable = condition::new(); // undeclared type or module `condition`
        println!("{:?}", testable::new());
    }
}

标签: rust

解决方案


似乎您有一个表示类型的枚举,以及一​​个与枚举变体同名的结构。

请注意,枚举变体名称与它们可能代表的任何类型无关。

此外,Rust 中不存在反射(不是 Java 意义上的),因此您不能拥有包含类型名称的值并从中创建该类型。

但是,可以获取一个未知值的枚举(类型检查器无论如何都不能约束枚举值),并基于此枚举返回一个值。

此外,虽然方法可能不会直接返回未知类型,但您可以使用 aBox<dyn Trait>来包装未知类型的值,或者创建一个实现该特征的枚举并委托给密封实现。

以下可能更接近您想要的:

pub enum ConditionTypes {
    SmaCheck,
    CandlesPassed,
}

pub enum Condition {
    SmaCheck(SmaCheck), // the first word is the enum variant, the second word is the type of the value it contains
    CandlesPassed(CandlesPassed),
}

impl ConditionType {
    pub fn new(&self) -> Condition {
        match self {
            Self::SmaCheck => Condition::SmaCheck(SmaCheck::new()),
            Self::CandlesPassed => Condition::CandlesPassed(CandlesPassed::new()),
        }
    }
}

pub trait Testable {
    // we don't really need new() in this trait, do we?
    // if you want to use this trait when it could be of runtime-unknown type
    // instead of compile-time generics, all methods must have a receiver.

    fn test(&self, candle: &Candle) -> bool;
}

impl Testable for Condition {
    fn test(&self, candle: &Candle) -> bool {
        match self {
            Condition::SmaCheck(inner) => inner.test(candle),
            Condition::CandlesPassed(inner) => inner.test(candle),
        }
    }
}

// impl Testable for SmaCheck and CandlesPassed omitted

这看起来有点样板,但是有宏可以派生它。


推荐阅读