rust - 构造类型的向量并初始化它们
问题描述
我试图拥有某种类型的列表,然后我可以初始化和构建遗传算法。
问题在于使用“类型”本身,我还没有找到正确的方法来获取一系列类型并调用::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 中不存在反射(不是 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
这看起来有点样板,但是有宏可以派生它。