Rust如何返回包裹不同类型Option的Vec并实现结构体必填字段校验
错误原因分析
你定义的泛型T由调用侧指定具体类型,但你尝试放入Vec的元素分别是Option<i64>和Option<String>两种不同类型的值,自然会报类型不匹配错误。且你的校验逻辑只关心字段是否为None,完全不需要感知内部存储的具体类型,使用泛型或者trait对象都属于多余设计。
另外你最初的has_essentials逻辑写反了:现有代码是所有核心字段均为None时返回true,和你要求的「核心字段全部不为None」的需求刚好相反。
实现方案
方案1:仅需校验,不需要使用核心字段值
如果你不需要后续使用核心字段的实际值,只需要做校验,可以把所有Option统一转为仅保留是否有值信息的Option<()>,类型完全统一,无额外开销:
impl MyType { fn get_essentials(&self) -> Vec<Option<()>> { vec![ self.id.as_ref().map(|_| ()), self.id_str.as_ref().map(|_| ()), self.abbrv.as_ref().map(|_| ()), self.title.as_ref().map(|_| ()), ] } fn has_essentials(&self) -> bool { // 所有元素都是Some即代表所有核心字段都不为None self.get_essentials().iter().all(|f| f.is_some()) } }
方案2:需要后续使用核心字段值(推荐)
如果你需要返回克隆后的核心字段供后续逻辑使用,最优雅的方式是定义专门的核心字段结构体,完全类型安全,无运行时开销,后续调整核心字段范围只需要修改结构体和get_essentials构造逻辑即可:
// 专门存储非空的核心字段 struct EssentialFields { id: i64, id_str: String, abbrv: String, title: String, } impl MyType { // 所有核心字段都存在时返回填充好的结构体,否则返回None fn get_essentials(&self) -> Option<EssentialFields> { Some(EssentialFields { id: self.id.clone()?, id_str: self.id_str.clone()?, abbrv: self.abbrv.clone()?, title: self.title.clone()?, }) } fn has_essentials(&self) -> bool { self.get_essentials().is_some() } }
后续你拿到EssentialFields实例时所有字段都是非Option类型,不需要额外判空,使用起来非常方便。
不推荐的方案:返回trait对象Vec
如果你一定要返回包含不同类型值的Vec,可以用 trait 对象实现,但会引入堆分配开销,后续取值需要向下转型,使用成本很高,仅做参考:
impl MyType { fn get_essentials(&self) -> Vec<Option<Box<dyn ToString>>> { vec![ self.id.clone().map(|v| Box::new(v) as Box<dyn ToString>), self.id_str.clone().map(|v| Box::new(v) as Box<dyn ToString>), self.abbrv.clone().map(|v| Box::new(v) as Box<dyn ToString>), self.title.clone().map(|v| Box::new(v) as Box<dyn ToString>), ] } fn has_essentials(&self) -> bool { self.get_essentials().iter().all(|f| f.is_some()) } }
内容的提问来源于stack exchange,提问作者MikeTheSapien
相关产品推荐
相关产品推荐

